谁能用Delphi屏蔽Win2000的Alt+Ctrl+Del!分数任你要!!!(UP有分) 谁能用Delphi屏蔽Win2000的Alt+Ctrl+Del!分数任你要!可另开贴送分! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 Win2K/NT下屏蔽Ctrl+Alt+Del的响应大家知道,Ctrl+Alt+Del是Win2k/NT操作系统默认的系统登录/注销组合键序列,系统级别很高。在应用程序中,想要屏蔽掉该键序列的响应或得到这个"按下"事件,难度是相当大的。本文介绍了一种简单易行的方法,实现在用户登录成功后,按下Ctrl+Alt+Del不再弹出"Windows安全"对话框。关键词:GINA(Graphical Identification aNd Authentication)SAS(Secure Attention Sequence)一. 开发原理首先介绍一下Winlogon。Windows 2000/NT有三种系统状态:没有用户登录状态、用户成功登录状态以及工作站锁定状态。Winlogon是Windows 2000/NT操作系统提供交互式登录支持的组件。Winlogon有三个组成部分:可执行文件winlogon.exe,提供图形界面认证功能的动态库Gina Dll,以及一些网络服务提供动态库Network Provider Dll。参考模型如下: winlogon.exe处理一些下层导出的接口函数,而认证策略是在Gina Dll中是独立设计的。在系统启动时,Gina Dll被winlogon.exe装载。Microsoft提供了一个默认的Gina Dll--Winnt\system32\msgina.dll,提供了标准的用户名、密码认证模式。Gina Dll是可替换的,用户可以设计自己的Gina Dll,以提供其他如智能卡、视网膜、指纹或其他一些认证机制。开发自定义的Gina Dll。必须实现并导出与winlogon.exe交互的18个标准函数接口,包括WlxNegotiate、WlxInitialize、WlxLoggedOnSAS等(其他函数接口请参考Msdn)。其中WlxNegotiate是winlogon.exe调用的第一个接口函数,进行必要的版本判断,随后调用的是WlxInitialize,主要完成winlogon.exe特定版本的函数分派表向Gina Dll的传递。笔者还要说明的是WlxLoggedOnSAS函数,这个函数主要的功能是,当winlogon在登录成功状态下,接收到SAS事件,于是调用这个函数进行SAS事件的识别以及进行各事件的相应处理。自定义Gina Dll的使用。比如开发的Gina Dll文件名为MyGina.dll。将该文件放到以下路径:Winnt\system32。并修改注册表,如下:Key Name: \HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\ Winlogon Value Name: GinaDLL Value Type: [REG_SZ]Value: MyGina.dll重新启动计算机MyGina.dll即投入使用。二. 应用实例应用要求:在用户登录成功状态下,按下Ctrl+Alt+Del时系统不再弹出"Widows安全"对话框。由于并不需要改变用户名、密码这种标准的认证模式,所以可以仍然使用msgina.dll中导出的函数接口,而对WlxLoggedOnSAS函数的实现进行必要的改变。开发环境:Windows 2000,PII 400开发工具:Microsoft Visual C++ 6.0开发步骤:1.新建项目,选择MFC AppWizard(dll),项目名输入为MyGina。按下"OK"后,选择Regular DLL with MFC statically linked,按下"Finish"。2.使用View->ClassWizard为CmyGinaApp增加InitInstance和ExitInstance两个函数的覆盖。注意在Stdafx.h中加入#include <Winwlx.h>。3.由于要导入msgina.dll的接口函数,所以在MyGina.h中定义接口函数变量类型,如下:typedef (WINAPI * NEGOTIATE) (DWORD,PDWORD);typedef (WINAPI * INITIALIZE) (LPWSTR,HANDLE,PVOID,PVOID,PVOID *);typedef (WINAPI * ACTIVATE_USHELL) (PVOID,PWSTR,PWSTR,PVOID);typedef (WINAPI * PARAM_PVOID) (PVOID);typedef (WINAPI * DISP_STATUS) (PVOID,HDESK,DWORD,PWSTR,PWSTR);typedef (WINAPI * GET_STATUS) (PVOID,DWORD *,PWSTR,DWORD);typedef (WINAPI * LOGON_SAS) (PVOID,DWORD,PVOID);typedef (WINAPI * LOGOUT_SAS) (PVOID,DWORD,PLUID,PSID,PDWORD, PHANDLE,WLX_MPR_NOTIFY_INFO,PVOID *);typedef (WINAPI * NETWORK_LOAD) (PVOID,PWLX_MPR_NOTIFY_INFO);typedef (WINAPI * SCR_SAVER) (PVOID,BOOL *);typedef (WINAPI * SHUT_DOWN) (PVOID,DWORD);typedef (WINAPI * START_APP) (PVOID,PWSTR,PVOID,PWSTR);typedef (WINAPI * LOCKED_SAS) (PVOID,DWORD);并在类CmyGinaApp中定义成员变量,如下:private:HMODULE hMsDll;public:NEGOTIATE MyWlxNegotiate;INITIALIZE MyWlxInitialize;ACTIVATE_USHELL MyWlxActivateUserShell;PARAM_PVOID MyWlxDisplayLockedNotice;PARAM_PVOID MyWlxDisplaySASNotice;DISP_STATUS MyWlxDisplayStatusMessage;GET_STATUS MyWlxGetStatusMessage;PARAM_PVOID MyWlxIsLockOk;PARAM_PVOID MyWlxIsLogoffOk;LOGON_SAS MyWlxLoggedOnSAS;LOGOUT_SAS MyWlxLoggedOutSAS;PARAM_PVOID MyWlxLogoff;NETWORK_LOAD MyWlxNetworkProviderLoad;PARAM_PVOID MyWlxRemoveStatusMessage;SCR_SAVER MyWlxScreenSaverNotify;SHUT_DOWN MyWlxShutdown;START_APP MyWlxStartApplication;LOCKED_SAS MyWlxWkstaLockedSAS;注意在MyGina.h中说明extern CMyGinaApp theApp;以便于程序其他地方对theApp的引用。4.在MyGina.cpp中,实现InitInstance如下:// 得到默认的gina dllif (hMsDll == NULL){hMsDll = ::LoadLibrary("msgina.dll");}// 导入各个接口函数if (hMsDll != NULL){MyWlxNegotiate = (NEGOTIATE) GetProcAddress(hMsDll,"WlxNegotiate");MyWlxInitialize = (INITIALIZE) GetProcAddress(hMsDll,"WlxInitialize");MyWlxActivateUserShell=(ACTIVATE_USHELL) GetProcAddress(hMsDll,"WlxActivateUserShell");MyWlxDisplayLockedNotice=(PARAM_PVOID) GetProcAddress(hMsDll,"WlxDisplayLockedNotice");MyWlxDisplaySASNotice = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxDisplaySASNotice");MyWlxDisplayStatusMessage=(DISP_STATUS) GetProcAddress(hMsDll,"WlxDisplayStatusMessage");MyWlxGetStatusMessage = (GET_STATUS) GetProcAddress(hMsDll,"WlxGetStatusMessage");MyWlxIsLockOk = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxIsLockOk");MyWlxIsLogoffOk = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxIsLogoffOk");MyWlxLoggedOnSAS = (LOGON_SAS) GetProcAddress(hMsDll,"WlxLoggedOnSAS");MyWlxLoggedOutSAS = (LOGOUT_SAS) GetProcAddress(hMsDll,"WlxLoggedOutSAS");MyWlxLogoff = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxLogoff");MyWlxNetworkProviderLoad=(NETWORK_LOAD)GetProcAddress(hMsDll,"WlxNetworkProviderLoad");MyWlxRemoveStatusMessage=(PARAM_PVOID) GetProcAddress(hMsDll,"WlxRemoveStatusMessage");MyWlxScreenSaverNotify = (SCR_SAVER) GetProcAddress(hMsDll,"WlxScreenSaverNotify");MyWlxShutdown = (SHUT_DOWN) GetProcAddress(hMsDll,"WlxShutdown");MyWlxStartApplication = (START_APP) GetProcAddress(hMsDll,"WlxStartApplication");MyWlxWkstaLockedSAS = (LOCKED_SAS) GetProcAddress(hMsDll,"WlxWkstaLockedSAS");}实现ExitInstance如下:// 卸载dllif (hMsDll != NULL){::FreeLibrary(hMsDll);hMsDll = NULL;}5.实现接口函数。由于本应用仍然保持msgina.dll的大部分操作,所以MyGina.dll的接口函数的实现较为简单。重点需要注意的是WlxLoggedOnSAS函数的实现。当在成功登录状态下,不管接收到什么SAS事件,该函数直接返回WLX_SAS_ACTION_NONE而不做其他处理。由于实现的函数较多(必须的18个),笔者仅列出代表性的五个,其余的依理类推。// Winlogon.exe调用的gina dll中的第一个函数// 使gina dll确认是否支持当前版本的Winlogon.exe// 传递给winlogon.exe需要那个版本的接口函数BOOL WINAPI WlxNegotiate(DWORD dwWinLogonVersion, PDWORD pdwDllVersion){// 直接调用从msgina.dll中导入的函数return theApp.MyWlxNegotiate(dwWinLogonVersion,pdwDllVersion);}// 初始化,winlogon.exe向gina dll传递需要版本的接口函数分配表BOOL WINAPI WlxInitialize(LPWSTR lpWinsta, HANDLE hWlx, PVOID pvReserved, PVOID pWinlogonFunctions, PVOID * pWlxContext ){// 直接调用从msgina.dll中导入的函数return theApp.MyWlxInitialize(lpWinsta,hWlx,pvReserved,pWinlogonFunctions,pWlxContext);}// 当系统处于锁定状态时,Winlogon.exe调用该函数// 显示一些信息,如锁定者、锁定时间等VOID WINAPI WlxDisplayLockedNotice(PVOID pWlxContext){theApp.MyWlxDisplayLockedNotice(pWlxContext);}// 在系统关闭之前,Winlogon.exe调用该函数// 允许gina dll处理一些系统关闭前的处理VOID WINAPI WlxShutdown(PVOID pWlxContext, DWORD ShutdownType){theApp.MyWlxShutdown(pWlxContext,ShutdownType);}// 当系统处于登陆成功,没有锁定的状态下// Winlogon接收到SAS事件,于是调用该函数// 现屏蔽所有事件,直接返回int WINAPI WlxLoggedOnSAS(PVOID pWlxContext, DWORD dwSasType, PVOID pReserved){return WLX_SAS_ACTION_NONE;}6.将MyGina.dll中实现的所有接口函数,在MyGina.def中定义导出。 Win2K/NT下屏蔽Ctrl+Alt+Del的响应大家知道,Ctrl+Alt+Del是Win2k/NT操作系统默认的系统登录/注销组合键序列,系统级别很高。在应用程序中,想要屏蔽掉该键序列的响应或得到这个"按下"事件,难度是相当大的。本文介绍了一种简单易行的方法,实现在用户登录成功后,按下Ctrl+Alt+Del不再弹出"Windows安全"对话框。关键词:GINA(Graphical Identification aNd Authentication)SAS(Secure Attention Sequence)一. 开发原理首先介绍一下Winlogon。Windows 2000/NT有三种系统状态:没有用户登录状态、用户成功登录状态以及工作站锁定状态。Winlogon是Windows 2000/NT操作系统提供交互式登录支持的组件。Winlogon有三个组成部分:可执行文件winlogon.exe,提供图形界面认证功能的动态库Gina Dll,以及一些网络服务提供动态库Network Provider Dll。参考模型如下: winlogon.exe处理一些下层导出的接口函数,而认证策略是在Gina Dll中是独立设计的。在系统启动时,Gina Dll被winlogon.exe装载。Microsoft提供了一个默认的Gina Dll--Winnt\system32\msgina.dll,提供了标准的用户名、密码认证模式。Gina Dll是可替换的,用户可以设计自己的Gina Dll,以提供其他如智能卡、视网膜、指纹或其他一些认证机制。开发自定义的Gina Dll。必须实现并导出与winlogon.exe交互的18个标准函数接口,包括WlxNegotiate、WlxInitialize、WlxLoggedOnSAS等(其他函数接口请参考Msdn)。其中WlxNegotiate是winlogon.exe调用的第一个接口函数,进行必要的版本判断,随后调用的是WlxInitialize,主要完成winlogon.exe特定版本的函数分派表向Gina Dll的传递。笔者还要说明的是WlxLoggedOnSAS函数,这个函数主要的功能是,当winlogon在登录成功状态下,接收到SAS事件,于是调用这个函数进行SAS事件的识别以及进行各事件的相应处理。自定义Gina Dll的使用。比如开发的Gina Dll文件名为MyGina.dll。将该文件放到以下路径:Winnt\system32。并修改注册表,如下:Key Name: \HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\ Winlogon Value Name: GinaDLL Value Type: [REG_SZ]Value: MyGina.dll重新启动计算机MyGina.dll即投入使用。二. 应用实例应用要求:在用户登录成功状态下,按下Ctrl+Alt+Del时系统不再弹出"Widows安全"对话框。由于并不需要改变用户名、密码这种标准的认证模式,所以可以仍然使用msgina.dll中导出的函数接口,而对WlxLoggedOnSAS函数的实现进行必要的改变。开发环境:Windows 2000,PII 400开发工具:Microsoft Visual C++ 6.0开发步骤:1.新建项目,选择MFC AppWizard(dll),项目名输入为MyGina。按下"OK"后,选择Regular DLL with MFC statically linked,按下"Finish"。2.使用View->ClassWizard为CmyGinaApp增加InitInstance和ExitInstance两个函数的覆盖。注意在Stdafx.h中加入#include <Winwlx.h>。3.由于要导入msgina.dll的接口函数,所以在MyGina.h中定义接口函数变量类型,如下:typedef (WINAPI * NEGOTIATE) (DWORD,PDWORD);typedef (WINAPI * INITIALIZE) (LPWSTR,HANDLE,PVOID,PVOID,PVOID *);typedef (WINAPI * ACTIVATE_USHELL) (PVOID,PWSTR,PWSTR,PVOID);typedef (WINAPI * PARAM_PVOID) (PVOID);typedef (WINAPI * DISP_STATUS) (PVOID,HDESK,DWORD,PWSTR,PWSTR);typedef (WINAPI * GET_STATUS) (PVOID,DWORD *,PWSTR,DWORD);typedef (WINAPI * LOGON_SAS) (PVOID,DWORD,PVOID);typedef (WINAPI * LOGOUT_SAS) (PVOID,DWORD,PLUID,PSID,PDWORD, PHANDLE,WLX_MPR_NOTIFY_INFO,PVOID *);typedef (WINAPI * NETWORK_LOAD) (PVOID,PWLX_MPR_NOTIFY_INFO);typedef (WINAPI * SCR_SAVER) (PVOID,BOOL *);typedef (WINAPI * SHUT_DOWN) (PVOID,DWORD);typedef (WINAPI * START_APP) (PVOID,PWSTR,PVOID,PWSTR);typedef (WINAPI * LOCKED_SAS) (PVOID,DWORD);并在类CmyGinaApp中定义成员变量,如下:private:HMODULE hMsDll;public:NEGOTIATE MyWlxNegotiate;INITIALIZE MyWlxInitialize;ACTIVATE_USHELL MyWlxActivateUserShell;PARAM_PVOID MyWlxDisplayLockedNotice;PARAM_PVOID MyWlxDisplaySASNotice;DISP_STATUS MyWlxDisplayStatusMessage;GET_STATUS MyWlxGetStatusMessage;PARAM_PVOID MyWlxIsLockOk;PARAM_PVOID MyWlxIsLogoffOk;LOGON_SAS MyWlxLoggedOnSAS;LOGOUT_SAS MyWlxLoggedOutSAS;PARAM_PVOID MyWlxLogoff;NETWORK_LOAD MyWlxNetworkProviderLoad;PARAM_PVOID MyWlxRemoveStatusMessage;SCR_SAVER MyWlxScreenSaverNotify;SHUT_DOWN MyWlxShutdown;START_APP MyWlxStartApplication;LOCKED_SAS MyWlxWkstaLockedSAS;注意在MyGina.h中说明extern CMyGinaApp theApp;以便于程序其他地方对theApp的引用。4.在MyGina.cpp中,实现InitInstance如下:// 得到默认的gina dllif (hMsDll == NULL){hMsDll = ::LoadLibrary("msgina.dll");}// 导入各个接口函数if (hMsDll != NULL){MyWlxNegotiate = (NEGOTIATE) GetProcAddress(hMsDll,"WlxNegotiate");MyWlxInitialize = (INITIALIZE) GetProcAddress(hMsDll,"WlxInitialize");MyWlxActivateUserShell=(ACTIVATE_USHELL) GetProcAddress(hMsDll,"WlxActivateUserShell");MyWlxDisplayLockedNotice=(PARAM_PVOID) GetProcAddress(hMsDll,"WlxDisplayLockedNotice");MyWlxDisplaySASNotice = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxDisplaySASNotice");MyWlxDisplayStatusMessage=(DISP_STATUS) GetProcAddress(hMsDll,"WlxDisplayStatusMessage");MyWlxGetStatusMessage = (GET_STATUS) GetProcAddress(hMsDll,"WlxGetStatusMessage");MyWlxIsLockOk = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxIsLockOk");MyWlxIsLogoffOk = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxIsLogoffOk");MyWlxLoggedOnSAS = (LOGON_SAS) GetProcAddress(hMsDll,"WlxLoggedOnSAS");MyWlxLoggedOutSAS = (LOGOUT_SAS) GetProcAddress(hMsDll,"WlxLoggedOutSAS");MyWlxLogoff = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxLogoff");MyWlxNetworkProviderLoad=(NETWORK_LOAD)GetProcAddress(hMsDll,"WlxNetworkProviderLoad");MyWlxRemoveStatusMessage=(PARAM_PVOID) GetProcAddress(hMsDll,"WlxRemoveStatusMessage");MyWlxScreenSaverNotify = (SCR_SAVER) GetProcAddress(hMsDll,"WlxScreenSaverNotify");MyWlxShutdown = (SHUT_DOWN) GetProcAddress(hMsDll,"WlxShutdown");MyWlxStartApplication = (START_APP) GetProcAddress(hMsDll,"WlxStartApplication");MyWlxWkstaLockedSAS = (LOCKED_SAS) GetProcAddress(hMsDll,"WlxWkstaLockedSAS");}实现ExitInstance如下:// 卸载dllif (hMsDll != NULL){::FreeLibrary(hMsDll);hMsDll = NULL;}5.实现接口函数。由于本应用仍然保持msgina.dll的大部分操作,所以MyGina.dll的接口函数的实现较为简单。重点需要注意的是WlxLoggedOnSAS函数的实现。当在成功登录状态下,不管接收到什么SAS事件,该函数直接返回WLX_SAS_ACTION_NONE而不做其他处理。由于实现的函数较多(必须的18个),笔者仅列出代表性的五个,其余的依理类推。// Winlogon.exe调用的gina dll中的第一个函数// 使gina dll确认是否支持当前版本的Winlogon.exe// 传递给winlogon.exe需要那个版本的接口函数BOOL WINAPI WlxNegotiate(DWORD dwWinLogonVersion, PDWORD pdwDllVersion){// 直接调用从msgina.dll中导入的函数return theApp.MyWlxNegotiate(dwWinLogonVersion,pdwDllVersion);}// 初始化,winlogon.exe向gina dll传递需要版本的接口函数分配表BOOL WINAPI WlxInitialize(LPWSTR lpWinsta, HANDLE hWlx, PVOID pvReserved, PVOID pWinlogonFunctions, PVOID * pWlxContext ){// 直接调用从msgina.dll中导入的函数return theApp.MyWlxInitialize(lpWinsta,hWlx,pvReserved,pWinlogonFunctions,pWlxContext);}// 当系统处于锁定状态时,Winlogon.exe调用该函数// 显示一些信息,如锁定者、锁定时间等VOID WINAPI WlxDisplayLockedNotice(PVOID pWlxContext){theApp.MyWlxDisplayLockedNotice(pWlxContext);}// 在系统关闭之前,Winlogon.exe调用该函数// 允许gina dll处理一些系统关闭前的处理VOID WINAPI WlxShutdown(PVOID pWlxContext, DWORD ShutdownType){theApp.MyWlxShutdown(pWlxContext,ShutdownType);}// 当系统处于登陆成功,没有锁定的状态下// Winlogon接收到SAS事件,于是调用该函数// 现屏蔽所有事件,直接返回int WINAPI WlxLoggedOnSAS(PVOID pWlxContext, DWORD dwSasType, PVOID pReserved){return WLX_SAS_ACTION_NONE;}6.将MyGina.dll中实现的所有接口函数,在MyGina.def中定义导出。 unit Main;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls;type TMainForm = class(TForm) EnableBtn: TButton; DisableBtn: TButton; AboutBtn: TButton; ExitBtn: TButton; Bell1: TBevel; Image: TImage; procedure AboutBtnClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure EnableBtnClick(Sender: TObject); procedure DisableBtnClick(Sender: TObject); procedure ExitBtnClick(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure FormDestroy(Sender: TObject); private { Private declarations } public { Public declarations } end;var MainForm: TMainForm;implementationuses Hook;{$R *.dfm}type // Declaration from VC++ WINUSER.H // PKBDLLHOOKSTRUCT = ^KBDLLHOOKSTRUCT; KBDLLHOOKSTRUCT = record vkCode: DWORD; scanCode: DWORD; flags: DWORD; time: DWORD; dwExtraInfo: DWORD; end;const LLKHF_ALTDOWN = KF_ALTDOWN shr 8; WH_KEYBOARD_LL = 13;var hhkNTKeyboard: HHOOK; // 钩子句柄// 低级键盘钩子回调函数//function LowLevelKeyboardFunc(nCode: Integer; w_Param: WPARAM; l_Param: LPARAM): LRESULT; stdcall;var blEatKeystroke: Boolean; p: PKBDLLHOOKSTRUCT;begin blEatKeystroke := False; if nCode = HC_ACTION then begin case w_Param of WM_KEYDOWN, WM_SYSKEYDOWN, WM_KEYUP, WM_SYSKEYUP: begin p := PKBDLLHOOKSTRUCT(l_Param); // 进行按键过滤 blEatKeystroke := (((p^.vkCode = VK_TAB) and ((p^.flags and LLKHF_ALTDOWN) <> 0)) or ((p^.vkCode = VK_ESCAPE) and ((p^.flags and LLKHF_ALTDOWN) <> 0)) or ((p^.vkCode = VK_ESCAPE) and ((GetKeyState(VK_CONTROL) and $8000) <> 0)) or ((p^.vkCode = VK_DELETE) and ((p^.flags and LLKHF_ALTDOWN) <> 0) and ((GetKeyState(VK_CONTROL) and $8000) <> 0))); end; end; // End of Case end; if blEatKeystroke then begin Result := 1; // 捕获这些组合键,按键消息由自己处理,必须返回 1 Hook.ShowHookInfo; // 显示一个窗口,你可以改为自己的处理代码 end else // 其他的按键,交由别的线程处理(过滤) Result := CallNextHookEx(0, nCode, w_Param, l_Param);end;procedure TMainForm.AboutBtnClick(Sender: TObject);begin Application.MessageBox( PChar('Windows NT 键盘钩子演示程序'#13#10#13#10'作者:Phoenix2000,2001年7月。'), '关于本程序', 0);end;procedure TMainForm.FormCreate(Sender: TObject);begin hhkNTKeyboard := 0; // 钩子句柄初值end;procedure TMainForm.EnableBtnClick(Sender: TObject);begin // 挂上键盘钩子 // hhkNTKeyboard := SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardFunc, HInstance, 0); if hhkNTKeyboard <> 0 then Application.MessageBox('系统键盘钩子已经启动了!', '信息', 64) else Application.MessageBox('无法启动系统键盘钩子!', '错误', 16);end;procedure TMainForm.DisableBtnClick(Sender: TObject);begin // 解除键盘钩子 // if hhkNTKeyboard = 0 then Application.MessageBox('系统键盘钩子已经被禁止了!', '警告', 48) else begin UnhookWindowsHookEx(hhkNTKeyboard); // 卸载钩子 hhkNTKeyboard := 0; Hook.CleanHookForm; // 此行代码与钩子无关,不要误解,是我自己的窗体清除 Application.MessageBox('成功卸载系统键盘钩子!', '信息', 64) end;end;procedure TMainForm.ExitBtnClick(Sender: TObject);begin Close;end;procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);begin CanClose := (hhkNTKeyboard = 0); if not CanClose then Application.MessageBox('请先卸载系统键盘钩子,然后再退出本程序!', '警告', 48);end;procedure TMainForm.FormDestroy(Sender: TObject);begin if hhkNTKeyboard <> 0 then begin UnhookWindowsHookEx(hhkNTKeyboard); hhkNTKeyboard := 0; end; Hook.CleanHookForm;end;end. http://www.csdn.net/magazine/source/11/s200111.doc 当你不需要让用户按Alt+Enter、Ctrl+Alt+Del、Ctrl+Esc等功能键的时候加入以下代码:Vartemp:integer;beginSystemParametersInfo(Spi_screensaverrunning,1,@temp,0);end; 当你要恢复功能键时用以下代码:VarTemp:integer;beginSystemParametersInfo(spi_screensaverrunning,0,@temp,0);end; 呵呵,谢谢厉害…………学习ing …… 我有delphi的源码,xp下面不能用http://www.iligia.com/public/download/tkhotkey/ligia_tkhotkey_source.rar记得给分 呵呵,大哥,下载一个Delphi超级猛料吧!!!你看了,如果还不会,那就不怪我了http://www.eping.net 对,建议下载一个超级猛料或者//作者 :韦覃武,jiangsheng//网上呢称:BCB_FANS(四大名捕之追杀令)(此为CSDN和www.driverdevelop.com之帐号)jiangsheng(此为CSDN帐号)//E-Mail :[email protected]//日期 :2002-10-20//2002-11-5 jingsheng修改//功能 :在2000下屏蔽Ctrl + Alt + Del组合键。(在Windows 2000 Professional SP3// 中文版平台下面测试通过)//原理 :采用远程线程注入技术,装载一个DLL到Winlogon进程,然后截获SAS窗口的窗// 口过程,接管WM_HOTKEY消息,以达到屏蔽Ctrl + Alt + Del之目的。//开发语言:Borland C++Builder 5.0 Patch2,Visual C++ 6.0 SP5//技术比较:关于在2000下面如何屏蔽Ctrl + Alt + Del组合键,一种常被提到的解决方法就// 是使用自己写的GINA去替换MSGINA.DLL,然后在WlxLoggedOnSAS里边直接返回// WLX_SAS_ACTION_NONE。嘿嘿,说到底这并不是真正地屏蔽了这个组合键,只是// 直接返回WLX_SAS_ACTION_NONE时,Winlogon进程又自动从"Winlogon"桌面切换// 回原来的"Default"桌面了,而不是显示安全对话框,所以看起来被屏蔽了:),// 使用那种方法明显地看到桌面在闪烁!但是使用本文的方法时,你不会看到任// 何闪烁!//鸣谢 :www.driverdevelop.com上的icube和lu0。//版权 :转载请注明原作者:)//---------------------------------------------------------------------------#include "stdafx.h"#include <tlhelp32.h>#include <lmerr.h>#include "Hook.h"//add by jiangsheng 2002-11-5#include "TaskKeyMgr.h"#include "Wrappers.h"//复制自MSDN杂志Windows XP Escape from DLL Hell with Custom Debugging and Instrumentation Tools and Utilities的代码extern BOOL Is_Terminal_Services () ;//复制自Platform SDK文档: Windows System Information /Verifying the System Version//end add by jiangsheng 2002-11-5//---------------------------------------------------------------------------//错误代码格式化函数//replaced by jiangsheng 2002-11-5//from Q149409 HOWTO: Get Message Text from Networking Error CodesCString __fastcall SysErrorMessage(DWORD dwLastError ){CString strRet(_T("Unknown error"));HMODULE hModule = NULL; // default to system sourceLPSTR MessageBuffer;DWORD dwBufferLength;DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_IGNORE_INSERTS |FORMAT_MESSAGE_FROM_SYSTEM ;//// If dwLastError is in the network range,// load the message source.//if(dwLastError >= NERR_BASE && dwLastError <= MAX_NERR) {hModule = LoadLibraryEx(TEXT("netmsg.dll"),NULL,LOAD_LIBRARY_AS_DATAFILE);if(hModule != NULL)dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE;}//// Call FormatMessage() to allow for message// text to be acquired from the system// or from the supplied module handle.//if(dwBufferLength = FormatMessageA(dwFormatFlags,hModule, // module to get message from (NULL == system)dwLastError,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language(LPSTR) &MessageBuffer,0,NULL)){//// Output message string on stderr.//strRet=CString(MessageBuffer,dwBufferLength);//// Free the buffer allocated by the system.//LocalFree(MessageBuffer);}//// If we loaded a message source, unload it.//if(hModule != NULL)FreeLibrary(hModule);return strRet;}//end replaced by jiangsheng 2002-11-5//---------------------------------------------------------------------------#ifdef UNICODELPCSTR LoadLibraryFuncStr = "LoadLibraryW";LPCSTR GetModuleHandleFuncStr = "GetModuleHandleW";#elseLPCSTR LoadLibraryFuncStr = "LoadLibraryA";LPCSTR GetModuleHandleFuncStr = "GetModuleHandleA";#endifLPCSTR FreeLibraryFuncStr = "FreeLibrary";LPCSTR GetProcAddressFuncStr = "GetProcAddress";LPCSTR GetLastErrorFuncStr = "GetLastError";//---------------------------------------------------------------------------//removed by jiangsheng 2002-11-5//const char* const RemoteDllName = "RemoteDll.Dll";//end removed by jiangsheng 2002-11-5LPCTSTR szRemoteProcessName = "Winlogon.exe";typedef HINSTANCE (WINAPI *PLOADLIBRARY)(LPCTSTR );typedef BOOL (WINAPI *PFREELIBRARY)(HINSTANCE);typedef HMODULE (WINAPI* PGETMODULEHANDLE)(LPCTSTR );typedef PVOID (WINAPI* PGETPROCADDRESS)(HINSTANCE,LPCSTR);typedef DWORD (WINAPI* PGETLASTERROR)(VOID);BOOL __fastcall EnablePrivilege(LPCTSTR lpszPrivilegeName,BOOL bEnable);DWORD __fastcall GetPIDFromName(LPCTSTR lpszProcName);//---------------------------------------------------------------------------typedef struct{PLOADLIBRARY pfnLoadLibrary;PGETLASTERROR pfnGetLastError;TCHAR szDllName[1024];DWORD dwReturnValue;} INJECTLIBINFO;typedef struct{PFREELIBRARY pfnFreeLibrary;PGETMODULEHANDLE pfnGetModuleHandle;PGETLASTERROR pfnGetLastError;DWORD dwReturnValue;TCHAR szDllName[1024];} DEINJECTLIBINFO;//---------------------------------------------------------------------------//远程线程,用来装载DLLstatic DWORD WINAPI ThreadFuncAttach(INJECTLIBINFO *pInfo){HINSTANCE hDll=NULL;pInfo->dwReturnValue = 0;hDll = (HINSTANCE)pInfo->pfnLoadLibrary(pInfo->szDllName);if(hDll == NULL)pInfo->dwReturnValue = pInfo->pfnGetLastError();return((DWORD)hDll);}//---------------------------------------------------------------------------//占位函数,用来计算ThreadFuncAttach的大小static void AfterThreadFuncAttach(void){}//---------------------------------------------------------------------------//远程线程,用来卸载DLLstatic DWORD WINAPI ThreadFuncDetach(DEINJECTLIBINFO *pInfo){HINSTANCE hDll = NULL;BOOL bResult=FALSE;BOOL bHasFoundModule = FALSE;pInfo->dwReturnValue = 0;//意味成功,如果这个值不是0,则是一个错误代码。while((hDll = pInfo->pfnGetModuleHandle(pInfo->szDllName)) != NULL){bHasFoundModule = TRUE;bResult = pInfo->pfnFreeLibrary(hDll);if(bResult == FALSE){pInfo->dwReturnValue = pInfo->pfnGetLastError();break;}}if(pInfo->dwReturnValue == 0 && !bHasFoundModule){pInfo->dwReturnValue = pInfo->pfnGetLastError();}return 1;}//---------------------------------------------------------------------------//占位函数,用来计算ThreadFuncDetach的大小static void AfterThreadFuncDetach(void){}//---------------------------------------------------------------------------//修改本进程的权限BOOL __fastcall EnablePrivilege(LPCTSTR lpszPrivilegeName,BOOL bEnable){HANDLE hToken;TOKEN_PRIVILEGES tp;LUID luid;if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES |TOKEN_QUERY | TOKEN_READ,&hToken))return FALSE;if(!LookupPrivilegeValue(NULL, lpszPrivilegeName, &luid))return TRUE;tp.PrivilegeCount = 1;tp.Privileges[0].Luid = luid;tp.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0;AdjustTokenPrivileges(hToken,FALSE,&tp,NULL,NULL,NULL);CloseHandle(hToken);return (GetLastError() == ERROR_SUCCESS);}//--------------------------------------------------------------------------- //通过进程名称得到进程的ID(这里使用方法Toolhelp函数,也可使用PSAPI)DWORD __fastcall GetPIDFromName(LPCTSTR lpszProcName){HANDLE hSnapshot;PROCESSENTRY32 ProcStruct;DWORD dwProcessID = -1;//added by jiangsheng 2002-11-8BOOL bIsTerminalServices=Is_Terminal_Services();if(bIsTerminalServices){//复制自MSDN杂志Windows XP Escape from DLL Hell with Custom Debugging and Instrumentation Tools and Utilities的代码//get current session IDCWTSWrapper WTS;if (WTS.IsValid()){DWORD dwCurSessionID = -1;LPTSTR pSessionInfo=NULL;DWORD dwBytes;if(WTS.WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,WTS_CURRENT_SESSION,WTSSessionId, (LPTSTR*)&pSessionInfo, &dwBytes)){dwCurSessionID =*((DWORD*)pSessionInfo);// enumerate processesPWTS_PROCESS_INFO pProcessInfo = NULL;DWORD ProcessCount = 0;BOOL bFound;if (WTS.WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1,&pProcessInfo, &ProcessCount)){for (DWORD CurrentProcess = 0; CurrentProcess < ProcessCount; CurrentProcess++){CString strCurExePath(pProcessInfo[CurrentProcess].pProcessName);CString strRemoteProc(lpszProcName);strCurExePath.MakeLower();strRemoteProc.MakeLower();bFound = (strCurExePath.Find(strRemoteProc) != -1);if(bFound && dwCurSessionID==pProcessInfo[CurrentProcess].SessionId) {dwProcessID = pProcessInfo[CurrentProcess].ProcessId;break;}}}WTS.WTSFreeMemory(pSessionInfo);}}}else{//end added by jiangsheng 2002-11-8BOOL bResult;hSnapshot = CreateToolhelp32Snapshot((DWORD)TH32CS_SNAPPROCESS,0);ProcStruct.dwSize = sizeof(PROCESSENTRY32);bResult = Process32First(hSnapshot,&ProcStruct);while(bResult){BOOL bFound;CString strCurExePath(ProcStruct.szExeFile);CString strRemoteProc(lpszProcName);strCurExePath.MakeLower();strRemoteProc.MakeLower();bFound = (strCurExePath.Find(strRemoteProc) != -1);if(bFound){dwProcessID = ProcStruct.th32ProcessID;break;}bResult = Process32Next(hSnapshot,&ProcStruct);}CloseHandle(hSnapshot);}return dwProcessID;}//---------------------------------------------------------------------------// 插入代码//---------------------------------------------------------------------------//InjectFuncvoid __fastcall InjectFunc(){HANDLE hRemoteProcess=NULL;DWORD dwRemoteProcess=NULL;DWORD dwThreadSize=0;INJECTLIBINFO InjectLibInfo;PVOID pRemoteThread=NULL;PVOID pRemoteParam=NULL;DWORD dwWriten=0;DWORD dwRet=0;//提升本进程权限然后打开目的进程//当前用户必须具有调试权限EnablePrivilege(SE_DEBUG_NAME,true);dwRemoteProcess = GetPIDFromName(szRemoteProcessName);if(dwRemoteProcess == (DWORD)-1){MessageBox(NULL,_T("Failed to Query Process ID."),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);return;}hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS,false,dwRemoteProcess);if(hRemoteProcess == NULL){MessageBox(NULL,_T("Failed to Open Process. Err = ") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);return;}//初始化参数ZeroMemory(&InjectLibInfo,sizeof(INJECTLIBINFO ));InjectLibInfo.pfnLoadLibrary = (PLOADLIBRARY)GetProcAddress(GetModuleHandle("Kernel32.dll"),LoadLibraryFuncStr);InjectLibInfo.pfnGetLastError = (PGETLASTERROR)GetProcAddress(GetModuleHandle("Kernel32.dll"),GetLastErrorFuncStr);lstrcpyn(InjectLibInfo.szDllName,CTaskKeyMgr::strRemoteDllName,CTaskKeyMgr::strRemoteDllName.GetLength()+1);//在远程线程分配内存来存放参数pRemoteParam = VirtualAllocEx(hRemoteProcess,NULL,sizeof(INJECTLIBINFO),MEM_COMMIT,PAGE_READWRITE);if(pRemoteParam == NULL){MessageBox(NULL,_T("Failed to Allocate Memory at Remote Process for Param.Err = ") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);return;}dwRet = WriteProcessMemory(hRemoteProcess,pRemoteParam,(LPVOID)&InjectLibInfo,sizeof(INJECTLIBINFO),&dwWriten);if(dwRet == 0){MessageBox(NULL,_T("Failed to Write Param to Remote Process.Err = ") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);return;}//拷贝线程体dwThreadSize = (int)AfterThreadFuncAttach - (int)ThreadFuncAttach + 1024 + sizeof(INJECTLIBINFO);pRemoteThread = VirtualAllocEx(hRemoteProcess,NULL,dwThreadSize,MEM_COMMIT,PAGE_READWRITE);if(pRemoteThread == NULL){MessageBox(NULL,_T("Failed to Allocate Memory at Remote Process for Thread Code.Err = ") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);return;}dwRet = WriteProcessMemory(hRemoteProcess,pRemoteThread,(LPVOID)ThreadFuncAttach,dwThreadSize,&dwWriten);if(dwRet == 0){MessageBox(NULL,_T("Failed to Write Thread Code to Remote Process.Err = ") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);return;}//启动远程线程HANDLE hRemoteThread;hRemoteThread = CreateRemoteThread(hRemoteProcess,0,0,(DWORD(__stdcall *)(VOID*))pRemoteThread,(INJECTLIBINFO*)pRemoteParam,0,&dwWriten);::WaitForSingleObject(hRemoteThread,INFINITE); if(hRemoteThread == NULL){MessageBox(NULL,_T("Failed to create unload thread.Err=") + SysErrorMessage(GetLastError()),NULL,MB_OK |MB_APPLMODAL | MB_ICONWARNING);}else{;}//读卸载返回值dwRet =ReadProcessMemory(hRemoteProcess,pRemoteParam,(LPVOID)&InjectLibInfo,sizeof(INJECTLIBINFO),&dwWriten);if(dwRet == 0){MessageBox(NULL,_T("Unable to read load return value.Err=") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);}else{if(InjectLibInfo.dwReturnValue == 0){;}else{MessageBox(NULL,_T("Failed to load library to Winlogon.Err=") +SysErrorMessage(InjectLibInfo.dwReturnValue),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);}}//恢复权限EnablePrivilege(SE_DEBUG_NAME,false);CloseHandle(hRemoteProcess);}//---------------------------------------------------------------------------// 卸载线程//---------------------------------------------------------------------------//DeinjectFuncvoid __fastcall DeinjectFunc(){HANDLE hRemoteProcess=NULL;DWORD dwRemoteProcess=0;DWORD dwThreadSize=0;DEINJECTLIBINFO DeinjectLibInfo;PVOID pRemoteThread=NULL;PVOID pRemoteParam=NULL;DWORD dwWriten=0;DWORD Ret=0;//提升本进程权限然后打开目的进程EnablePrivilege(SE_DEBUG_NAME,true);dwRemoteProcess = GetPIDFromName(szRemoteProcessName);if(dwRemoteProcess == (DWORD)-1){MessageBox(NULL,_T("Failed to Query Process ID."),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);return;}hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS,false,dwRemoteProcess);if(hRemoteProcess == NULL){MessageBox(NULL,_T("Failed to Open Process. Err = ") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);return;}//初始化参数 ZeroMemory(&DeinjectLibInfo,sizeof(DEINJECTLIBINFO ));DeinjectLibInfo.pfnFreeLibrary = (PFREELIBRARY)GetProcAddress(GetModuleHandle("Kernel32.dll"),FreeLibraryFuncStr);DeinjectLibInfo.pfnGetModuleHandle = (PGETMODULEHANDLE)GetProcAddress(GetModuleHandle("Kernel32.dll"),GetModuleHandleFuncStr);DeinjectLibInfo.pfnGetLastError = (PGETLASTERROR)GetProcAddress(GetModuleHandle("Kernel32.dll"),GetLastErrorFuncStr);lstrcpyn(DeinjectLibInfo.szDllName,CTaskKeyMgr::strRemoteDllName,CTaskKeyMgr::strRemoteDllName.GetLength()+1);//在远程线程分配内存来存放参数pRemoteParam = VirtualAllocEx(hRemoteProcess,NULL,sizeof(DEINJECTLIBINFO),MEM_COMMIT,PAGE_READWRITE);if(pRemoteParam == NULL){MessageBox(NULL,_T("Failed to Allocate Memory at Remote Process.Err = ") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);}Ret = WriteProcessMemory(hRemoteProcess,pRemoteParam,(LPVOID)&DeinjectLibInfo,sizeof(DEINJECTLIBINFO),&dwWriten);if(Ret == 0){MessageBox(NULL,_T("Failed to Write Param to Remote Process.Err = ") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);return;}//拷贝线程体dwThreadSize = (int)AfterThreadFuncDetach - (int)ThreadFuncDetach + 1024 + sizeof(DEINJECTLIBINFO);pRemoteThread = VirtualAllocEx(hRemoteProcess,NULL,dwThreadSize,MEM_COMMIT,PAGE_READWRITE);if(pRemoteThread == NULL){MessageBox(NULL,_T("Failed to Allocate Memory at Remote Process for Thread Code.Err = ") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);return;}Ret = WriteProcessMemory(hRemoteProcess,pRemoteThread,(LPVOID)ThreadFuncDetach,dwThreadSize,&dwWriten);if(Ret == 0){MessageBox(NULL,_T("Failed to Write Thread Code to Remote Process.Err = ") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);return;}//启动远程线程HANDLE hRemoteThread;hRemoteThread = CreateRemoteThread(hRemoteProcess ,0,0,(DWORD(__stdcall *)(VOID*))pRemoteThread,(DEINJECTLIBINFO*)pRemoteParam,0,&dwWriten);if(hRemoteThread == NULL){MessageBox(NULL,_T("Failed to create remote unload thread.Err=") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);}else{CloseHandle(hRemoteThread);}//读卸载返回值Ret = ReadProcessMemory(hRemoteProcess,pRemoteParam,(LPVOID)&DeinjectLibInfo,sizeof(DEINJECTLIBINFO),&dwWriten);if(Ret == 0){MessageBox(NULL,_T("Unable to read unload return value.Err=") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);}else{if(DeinjectLibInfo.dwReturnValue == 0){ }else{MessageBox(NULL,_T("Failed to unload .Err=")+ SysErrorMessage(DeinjectLibInfo.dwReturnValue),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);}}//恢复权限CloseHandle(hRemoteProcess);EnablePrivilege(SE_DEBUG_NAME,false);}//---------------------------------------------------------------------------//使用方法 BOOL CTaskKeyMgr::IsCtrlAltDeleteDisabled(){return bInjectFuncLoaded;} if (dwFlags & CTRLALTDEL) {if(bDisable&&!IsCtrlAltDeleteDisabled()){InjectFunc();bInjectFuncLoaded=TRUE;}if(!bDisable&&IsCtrlAltDeleteDisabled()){DeinjectFunc();bInjectFuncLoaded=FALSE;}} 呵呵,很容易的Win2000和2003下有效下载:http://www.iligia.com/public/download/tkhotkey/ligia_tkhotkey_source.rar 兄弟,问问题有点点新意好不好!这种问题自己去看看KINGRON的猛料或是HUBDOG的葵花宝典! 谢谢各位!我要的是Win2000下的,、要在我的应用中进行控制,不是系统启动时! WINDOWS NT/2000 下如何屏蔽 CTRL+ALT+DEL作者 :ac952_z_cn前言 在 WINDOWS 9X 环境中我们可以使用 SystemParametersInfo (SPI_SCREENSAVERRUNNING, 1,NULL, 0); 来屏蔽 CTRL+ALT+DEL,但在 NT/2000 环境下却行不通 ,即使使用 WH_KEYBOARD_LL 这个低级的键盘 hook 也无法拦截!笔者通过替换 GINA DLL 的方式很好地实现了在 NT/2000 下屏蔽 CTRL+ALT+DEL 的功能。 下载源代码 6K一、原理 在 NT/2000 中交互式的登陆支持是由 WinLogon 调用 GINA DLL 实现的 ,GINA DLL 提供了一个交互式的界面为用户登陆提供认证请求。在 WinLogon 初始化时 ,就向系统注册截获 CTRL+ALT+DEL 消息 ,所以其他程序就无法得到 CTRL+ALT+DEL 的消息。 WinLogon 会和 GINA DLL 进行交互 ,缺省是 MSGINA.DLL( 在 System32 目录下 ) 。微软同时也为我们提供的接口 ,自己 可以编 GINA DLL 来代替 MSGINA.DLL 。 WinLogon 初始化时会创建 3 个桌面 :(1) 、 winlogon 桌面 : 主要显示 window 安全等界面 ,如你按下 CTRL+ALT+DEL,登陆的界面等 (2) 、应用程序桌面 : 我们平时见到的那个有我的电脑的界面 (3) 、屏幕保护桌面 : 屏幕保护显示界面。 在用户登陆以后 ,按下 CTRL+ALT+DEL 键的时候 ,WinLogon 回调用 GINA DLL 的输出函数 :WlxLoggedOnSAS,这时正处于 winlogon 桌面 ,我们只要直接将他转向应用程序桌面 ,系统就不会显示 Windows 安全那个界面 ,换一种说法 也就是用户按下 CTRL+ALT+DEL 后 ,不会起什么作用。当是我们在切换桌面的时候会出现屏幕闪动! 二、程序实现 GINA DLL 要输出下列函数 (winlogon 会调用 )WlxActivateUserShellWlxDisplayLockedNoticeWlxDisplaySASNoticeWlxDisplayStatusMessageWlxGetStatusMessageWlxInitializeWlxIsLockOkWlxIsLogoffOkWlxLoggedOnSASWlxLoggedOutSASWlxLogoffWlxNegotiateWlxNetworkProviderLoadWlxRemoveStatusMessageWlxScreenSaverNotifyWlxShutdownWlxStartApplicationWlxWkstaLockedSAS为了简化编程 ,我们从 MSGINA.DLL 中动态获取上诉函数 ,在自定义的 DLL 中 ( 以下称为 NoReboot.DLL) 中直接调用 MSGINA.DLL的函数即可。现在我们要处理的就是 WlxLoggedOnSAS 函数 :int WINAPI WlxLoggedOnSAS (PVOID pWlxContext,DWORD dwSasType,PVOID pReserved){HANDLE hMutex;WriteInfo("WlxLoggedOnSAS \r\n"); // 用于记录信息 if (dwSasType == WLX_SAS_TYPE_CTRL_ALT_DEL){ // 屏蔽 CTRL_ALT_DEL,也可以根据特定条件来决定是否要屏蔽 // 我采用了 Mutex 来控制是否屏蔽 ,( 注意 : 要用 unicode)hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, L"_ac952_z_cn_CTRL_ALT_DEL");if (hMutex){CloseHandle(hMutex);WriteInfo("disble CTRL+ALT+DEL \r\n");return WLX_SAS_ACTION_NONE; // 将屏幕切换到应用程序桌面 ,屏蔽掉 CTRL+ALT+DEL}elseWriteInfo("not disble CTRL+ALT+DEL \r\n");}return prcWlxLoggedOnSAS ( // 这是我从 MSGINA.DLL 中获取的函数。 pWlxContext,dwSasType,pReserved);}我们要在自己的程序中调用 hMutex = CreateMutex(NULL, FALSE, "_ac952_z_cn_CTRL_ALT_DEL"); 就可屏蔽 CTRL+ALT+DEL 。 三、安装和注意事项 :在编写 GIAN DLL 中要注意 ,GINA DLL 使用的是 unicode 。 GINA DLL 的安装 :键名 : \HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon变量名 : GinaDLL变量类型 : [REG_SZ]内容 : " 你的 GINA DLL 的名称 " 如 :"NoReboot.DLL:将你的 GINA DLL(NoReboot.dll) 拷贝到系统目录下 (system32),重启机器 ,你的 GINA DLL(NoReboot.dll) 就会运行。 如果出现进不了你的系统 ,那你进入 DOS 后 ,将 msgina.dll 拷贝成你的 GINA DLL(NoReboot.dll) 就可进入了 ,或者进入 安全模式 ,删除掉那个键值。 谢谢各位!我要的是Win2000下的,、要在我的应用中进行控制,不是系统启动时! DELPHI关于浮点型数据的比较 一个简单问题,有3个edit和1个label控件 关于用ComboBox保存代码的问题,急ing 100分,求救!!!第二次 MDI子窗体的显示(急) 窗体上“最大化”“最小化”“关闭”用的是什么字体的符号? 请大家推荐一本介绍delphi常用组件的属性、事件、函数的中文书 窗体停靠问题! 请问高手们,做帮助用什么工具比较好而且简单?急!! 紧急求救!!!! 朋友急需:高分求解图像打印问题----分不够可以加 ljmanage进来接分
大家知道,Ctrl+Alt+Del是Win2k/NT操作系统默认的系统登录/注销组合键序列,系统级别很高。在应用程序中,想要屏蔽掉该键序列的响应或得到这个"按下"事件,难度是相当大的。本文介绍了一种简单易行的方法,实现在用户登录成功后,按下Ctrl+Alt+Del不再弹出"Windows安全"对话框。关键词:GINA(Graphical Identification aNd Authentication)
SAS(Secure Attention Sequence)一. 开发原理
首先介绍一下Winlogon。Windows 2000/NT有三种系统状态:没有用户登录状态、用户成功登录状态以及工作站锁定状态。Winlogon是Windows 2000/NT操作系统提供交互式登录支持的组件。Winlogon有三个组成部分:可执行文件winlogon.exe,提供图形界面认证功能的动态库Gina Dll,以及一些网络服务提供动态库Network Provider Dll。参考模型如下:
winlogon.exe处理一些下层导出的接口函数,而认证策略是在Gina Dll中是独立设计的。在系统启动时,Gina Dll被winlogon.exe装载。Microsoft提供了一个默认的Gina Dll--Winnt\system32\msgina.dll,提供了标准的用户名、密码认证模式。Gina Dll是可替换的,用户可以设计自己的Gina Dll,以提供其他如智能卡、视网膜、指纹或其他一些认证机制。
开发自定义的Gina Dll。必须实现并导出与winlogon.exe交互的18个标准函数接口,包括WlxNegotiate、WlxInitialize、WlxLoggedOnSAS等(其他函数接口请参考Msdn)。其中WlxNegotiate是winlogon.exe调用的第一个接口函数,进行必要的版本判断,随后调用的是WlxInitialize,主要完成winlogon.exe特定版本的函数分派表向Gina Dll的传递。笔者还要说明的是WlxLoggedOnSAS函数,这个函数主要的功能是,当winlogon在登录成功状态下,接收到SAS事件,于是调用这个函数进行SAS事件的识别以及进行各事件的相应处理。
自定义Gina Dll的使用。比如开发的Gina Dll文件名为MyGina.dll。将该文件放到以下路径:Winnt\system32。并修改注册表,如下:
Key Name: \HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\ Winlogon
Value Name: GinaDLL
Value Type: [REG_SZ]
Value: MyGina.dll
重新启动计算机MyGina.dll即投入使用。二. 应用实例
应用要求:在用户登录成功状态下,按下Ctrl+Alt+Del时系统不再弹出"Widows安全"对话框。由于并不需要改变用户名、密码这种标准的认证模式,所以可以仍然使用msgina.dll中导出的函数接口,而对WlxLoggedOnSAS函数的实现进行必要的改变。
开发环境:Windows 2000,PII 400
开发工具:Microsoft Visual C++ 6.0
开发步骤:
1.新建项目,选择MFC AppWizard(dll),项目名输入为MyGina。按下"OK"后,选择Regular DLL with MFC statically linked,按下"Finish"。
2.使用View->ClassWizard为CmyGinaApp增加InitInstance和ExitInstance两个函数的覆盖。注意在Stdafx.h中加入#include <Winwlx.h>。
3.由于要导入msgina.dll的接口函数,所以在MyGina.h中定义接口函数变量类型,如下:
typedef (WINAPI * NEGOTIATE) (DWORD,PDWORD);
typedef (WINAPI * INITIALIZE) (LPWSTR,HANDLE,PVOID,PVOID,PVOID *);
typedef (WINAPI * ACTIVATE_USHELL) (PVOID,PWSTR,PWSTR,PVOID);
typedef (WINAPI * PARAM_PVOID) (PVOID);
typedef (WINAPI * DISP_STATUS) (PVOID,HDESK,DWORD,PWSTR,PWSTR);
typedef (WINAPI * GET_STATUS) (PVOID,DWORD *,PWSTR,DWORD);
typedef (WINAPI * LOGON_SAS) (PVOID,DWORD,PVOID);
typedef (WINAPI * LOGOUT_SAS) (PVOID,DWORD,PLUID,PSID,PDWORD, PHANDLE,WLX_MPR_NOTIFY_INFO,PVOID *);
typedef (WINAPI * NETWORK_LOAD) (PVOID,PWLX_MPR_NOTIFY_INFO);
typedef (WINAPI * SCR_SAVER) (PVOID,BOOL *);
typedef (WINAPI * SHUT_DOWN) (PVOID,DWORD);
typedef (WINAPI * START_APP) (PVOID,PWSTR,PVOID,PWSTR);
typedef (WINAPI * LOCKED_SAS) (PVOID,DWORD);
并在类CmyGinaApp中定义成员变量,如下:
private:
HMODULE hMsDll;
public:
NEGOTIATE MyWlxNegotiate;
INITIALIZE MyWlxInitialize;
ACTIVATE_USHELL MyWlxActivateUserShell;
PARAM_PVOID MyWlxDisplayLockedNotice;
PARAM_PVOID MyWlxDisplaySASNotice;
DISP_STATUS MyWlxDisplayStatusMessage;
GET_STATUS MyWlxGetStatusMessage;
PARAM_PVOID MyWlxIsLockOk;
PARAM_PVOID MyWlxIsLogoffOk;
LOGON_SAS MyWlxLoggedOnSAS;
LOGOUT_SAS MyWlxLoggedOutSAS;
PARAM_PVOID MyWlxLogoff;
NETWORK_LOAD MyWlxNetworkProviderLoad;
PARAM_PVOID MyWlxRemoveStatusMessage;
SCR_SAVER MyWlxScreenSaverNotify;
SHUT_DOWN MyWlxShutdown;
START_APP MyWlxStartApplication;
LOCKED_SAS MyWlxWkstaLockedSAS;
注意在MyGina.h中说明extern CMyGinaApp theApp;以便于程序其他地方对theApp的引用。
4.在MyGina.cpp中,实现InitInstance如下:
// 得到默认的gina dll
if (hMsDll == NULL)
{
hMsDll = ::LoadLibrary("msgina.dll");
}
// 导入各个接口函数
if (hMsDll != NULL)
{
MyWlxNegotiate = (NEGOTIATE) GetProcAddress(hMsDll,"WlxNegotiate");
MyWlxInitialize = (INITIALIZE) GetProcAddress(hMsDll,"WlxInitialize");
MyWlxActivateUserShell=(ACTIVATE_USHELL) GetProcAddress(hMsDll,"WlxActivateUserShell");
MyWlxDisplayLockedNotice=(PARAM_PVOID) GetProcAddress(hMsDll,"WlxDisplayLockedNotice");
MyWlxDisplaySASNotice = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxDisplaySASNotice");
MyWlxDisplayStatusMessage=(DISP_STATUS) GetProcAddress(hMsDll,"WlxDisplayStatusMessage");
MyWlxGetStatusMessage = (GET_STATUS) GetProcAddress(hMsDll,"WlxGetStatusMessage");
MyWlxIsLockOk = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxIsLockOk");
MyWlxIsLogoffOk = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxIsLogoffOk");
MyWlxLoggedOnSAS = (LOGON_SAS) GetProcAddress(hMsDll,"WlxLoggedOnSAS");
MyWlxLoggedOutSAS = (LOGOUT_SAS) GetProcAddress(hMsDll,"WlxLoggedOutSAS");
MyWlxLogoff = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxLogoff");
MyWlxNetworkProviderLoad=(NETWORK_LOAD)GetProcAddress(hMsDll,"WlxNetworkProviderLoad");
MyWlxRemoveStatusMessage=(PARAM_PVOID) GetProcAddress(hMsDll,"WlxRemoveStatusMessage");
MyWlxScreenSaverNotify = (SCR_SAVER) GetProcAddress(hMsDll,"WlxScreenSaverNotify");
MyWlxShutdown = (SHUT_DOWN) GetProcAddress(hMsDll,"WlxShutdown");
MyWlxStartApplication = (START_APP) GetProcAddress(hMsDll,"WlxStartApplication");
MyWlxWkstaLockedSAS = (LOCKED_SAS) GetProcAddress(hMsDll,"WlxWkstaLockedSAS");
}
实现ExitInstance如下:
// 卸载dll
if (hMsDll != NULL)
{
::FreeLibrary(hMsDll);
hMsDll = NULL;
}
5.实现接口函数。由于本应用仍然保持msgina.dll的大部分操作,所以MyGina.dll的接口函数的实现较为简单。重点需要注意的是WlxLoggedOnSAS函数的实现。当在成功登录状态下,不管接收到什么SAS事件,该函数直接返回WLX_SAS_ACTION_NONE而不做其他处理。由于实现的函数较多(必须的18个),笔者仅列出代表性的五个,其余的依理类推。
// Winlogon.exe调用的gina dll中的第一个函数
// 使gina dll确认是否支持当前版本的Winlogon.exe
// 传递给winlogon.exe需要那个版本的接口函数
BOOL WINAPI WlxNegotiate(DWORD dwWinLogonVersion, PDWORD pdwDllVersion)
{
// 直接调用从msgina.dll中导入的函数
return theApp.MyWlxNegotiate(dwWinLogonVersion,pdwDllVersion);
}
// 初始化,winlogon.exe向gina dll传递需要版本的接口函数分配表
BOOL WINAPI WlxInitialize(LPWSTR lpWinsta,
HANDLE hWlx,
PVOID pvReserved,
PVOID pWinlogonFunctions,
PVOID * pWlxContext
)
{
// 直接调用从msgina.dll中导入的函数
return theApp.MyWlxInitialize(lpWinsta,hWlx,pvReserved,pWinlogonFunctions,pWlxContext);
}
// 当系统处于锁定状态时,Winlogon.exe调用该函数
// 显示一些信息,如锁定者、锁定时间等
VOID WINAPI WlxDisplayLockedNotice(PVOID pWlxContext)
{
theApp.MyWlxDisplayLockedNotice(pWlxContext);
}
// 在系统关闭之前,Winlogon.exe调用该函数
// 允许gina dll处理一些系统关闭前的处理
VOID WINAPI WlxShutdown(PVOID pWlxContext, DWORD ShutdownType)
{
theApp.MyWlxShutdown(pWlxContext,ShutdownType);
}
// 当系统处于登陆成功,没有锁定的状态下
// Winlogon接收到SAS事件,于是调用该函数
// 现屏蔽所有事件,直接返回
int WINAPI WlxLoggedOnSAS(PVOID pWlxContext,
DWORD dwSasType,
PVOID pReserved)
{
return WLX_SAS_ACTION_NONE;
}
6.将MyGina.dll中实现的所有接口函数,在MyGina.def中定义导出。
大家知道,Ctrl+Alt+Del是Win2k/NT操作系统默认的系统登录/注销组合键序列,系统级别很高。在应用程序中,想要屏蔽掉该键序列的响应或得到这个"按下"事件,难度是相当大的。本文介绍了一种简单易行的方法,实现在用户登录成功后,按下Ctrl+Alt+Del不再弹出"Windows安全"对话框。关键词:GINA(Graphical Identification aNd Authentication)
SAS(Secure Attention Sequence)一. 开发原理
首先介绍一下Winlogon。Windows 2000/NT有三种系统状态:没有用户登录状态、用户成功登录状态以及工作站锁定状态。Winlogon是Windows 2000/NT操作系统提供交互式登录支持的组件。Winlogon有三个组成部分:可执行文件winlogon.exe,提供图形界面认证功能的动态库Gina Dll,以及一些网络服务提供动态库Network Provider Dll。参考模型如下:
winlogon.exe处理一些下层导出的接口函数,而认证策略是在Gina Dll中是独立设计的。在系统启动时,Gina Dll被winlogon.exe装载。Microsoft提供了一个默认的Gina Dll--Winnt\system32\msgina.dll,提供了标准的用户名、密码认证模式。Gina Dll是可替换的,用户可以设计自己的Gina Dll,以提供其他如智能卡、视网膜、指纹或其他一些认证机制。
开发自定义的Gina Dll。必须实现并导出与winlogon.exe交互的18个标准函数接口,包括WlxNegotiate、WlxInitialize、WlxLoggedOnSAS等(其他函数接口请参考Msdn)。其中WlxNegotiate是winlogon.exe调用的第一个接口函数,进行必要的版本判断,随后调用的是WlxInitialize,主要完成winlogon.exe特定版本的函数分派表向Gina Dll的传递。笔者还要说明的是WlxLoggedOnSAS函数,这个函数主要的功能是,当winlogon在登录成功状态下,接收到SAS事件,于是调用这个函数进行SAS事件的识别以及进行各事件的相应处理。
自定义Gina Dll的使用。比如开发的Gina Dll文件名为MyGina.dll。将该文件放到以下路径:Winnt\system32。并修改注册表,如下:
Key Name: \HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\ Winlogon
Value Name: GinaDLL
Value Type: [REG_SZ]
Value: MyGina.dll
重新启动计算机MyGina.dll即投入使用。二. 应用实例
应用要求:在用户登录成功状态下,按下Ctrl+Alt+Del时系统不再弹出"Widows安全"对话框。由于并不需要改变用户名、密码这种标准的认证模式,所以可以仍然使用msgina.dll中导出的函数接口,而对WlxLoggedOnSAS函数的实现进行必要的改变。
开发环境:Windows 2000,PII 400
开发工具:Microsoft Visual C++ 6.0
开发步骤:
1.新建项目,选择MFC AppWizard(dll),项目名输入为MyGina。按下"OK"后,选择Regular DLL with MFC statically linked,按下"Finish"。
2.使用View->ClassWizard为CmyGinaApp增加InitInstance和ExitInstance两个函数的覆盖。注意在Stdafx.h中加入#include <Winwlx.h>。
3.由于要导入msgina.dll的接口函数,所以在MyGina.h中定义接口函数变量类型,如下:
typedef (WINAPI * NEGOTIATE) (DWORD,PDWORD);
typedef (WINAPI * INITIALIZE) (LPWSTR,HANDLE,PVOID,PVOID,PVOID *);
typedef (WINAPI * ACTIVATE_USHELL) (PVOID,PWSTR,PWSTR,PVOID);
typedef (WINAPI * PARAM_PVOID) (PVOID);
typedef (WINAPI * DISP_STATUS) (PVOID,HDESK,DWORD,PWSTR,PWSTR);
typedef (WINAPI * GET_STATUS) (PVOID,DWORD *,PWSTR,DWORD);
typedef (WINAPI * LOGON_SAS) (PVOID,DWORD,PVOID);
typedef (WINAPI * LOGOUT_SAS) (PVOID,DWORD,PLUID,PSID,PDWORD, PHANDLE,WLX_MPR_NOTIFY_INFO,PVOID *);
typedef (WINAPI * NETWORK_LOAD) (PVOID,PWLX_MPR_NOTIFY_INFO);
typedef (WINAPI * SCR_SAVER) (PVOID,BOOL *);
typedef (WINAPI * SHUT_DOWN) (PVOID,DWORD);
typedef (WINAPI * START_APP) (PVOID,PWSTR,PVOID,PWSTR);
typedef (WINAPI * LOCKED_SAS) (PVOID,DWORD);
并在类CmyGinaApp中定义成员变量,如下:
private:
HMODULE hMsDll;
public:
NEGOTIATE MyWlxNegotiate;
INITIALIZE MyWlxInitialize;
ACTIVATE_USHELL MyWlxActivateUserShell;
PARAM_PVOID MyWlxDisplayLockedNotice;
PARAM_PVOID MyWlxDisplaySASNotice;
DISP_STATUS MyWlxDisplayStatusMessage;
GET_STATUS MyWlxGetStatusMessage;
PARAM_PVOID MyWlxIsLockOk;
PARAM_PVOID MyWlxIsLogoffOk;
LOGON_SAS MyWlxLoggedOnSAS;
LOGOUT_SAS MyWlxLoggedOutSAS;
PARAM_PVOID MyWlxLogoff;
NETWORK_LOAD MyWlxNetworkProviderLoad;
PARAM_PVOID MyWlxRemoveStatusMessage;
SCR_SAVER MyWlxScreenSaverNotify;
SHUT_DOWN MyWlxShutdown;
START_APP MyWlxStartApplication;
LOCKED_SAS MyWlxWkstaLockedSAS;
注意在MyGina.h中说明extern CMyGinaApp theApp;以便于程序其他地方对theApp的引用。
4.在MyGina.cpp中,实现InitInstance如下:
// 得到默认的gina dll
if (hMsDll == NULL)
{
hMsDll = ::LoadLibrary("msgina.dll");
}
// 导入各个接口函数
if (hMsDll != NULL)
{
MyWlxNegotiate = (NEGOTIATE) GetProcAddress(hMsDll,"WlxNegotiate");
MyWlxInitialize = (INITIALIZE) GetProcAddress(hMsDll,"WlxInitialize");
MyWlxActivateUserShell=(ACTIVATE_USHELL) GetProcAddress(hMsDll,"WlxActivateUserShell");
MyWlxDisplayLockedNotice=(PARAM_PVOID) GetProcAddress(hMsDll,"WlxDisplayLockedNotice");
MyWlxDisplaySASNotice = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxDisplaySASNotice");
MyWlxDisplayStatusMessage=(DISP_STATUS) GetProcAddress(hMsDll,"WlxDisplayStatusMessage");
MyWlxGetStatusMessage = (GET_STATUS) GetProcAddress(hMsDll,"WlxGetStatusMessage");
MyWlxIsLockOk = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxIsLockOk");
MyWlxIsLogoffOk = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxIsLogoffOk");
MyWlxLoggedOnSAS = (LOGON_SAS) GetProcAddress(hMsDll,"WlxLoggedOnSAS");
MyWlxLoggedOutSAS = (LOGOUT_SAS) GetProcAddress(hMsDll,"WlxLoggedOutSAS");
MyWlxLogoff = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxLogoff");
MyWlxNetworkProviderLoad=(NETWORK_LOAD)GetProcAddress(hMsDll,"WlxNetworkProviderLoad");
MyWlxRemoveStatusMessage=(PARAM_PVOID) GetProcAddress(hMsDll,"WlxRemoveStatusMessage");
MyWlxScreenSaverNotify = (SCR_SAVER) GetProcAddress(hMsDll,"WlxScreenSaverNotify");
MyWlxShutdown = (SHUT_DOWN) GetProcAddress(hMsDll,"WlxShutdown");
MyWlxStartApplication = (START_APP) GetProcAddress(hMsDll,"WlxStartApplication");
MyWlxWkstaLockedSAS = (LOCKED_SAS) GetProcAddress(hMsDll,"WlxWkstaLockedSAS");
}
实现ExitInstance如下:
// 卸载dll
if (hMsDll != NULL)
{
::FreeLibrary(hMsDll);
hMsDll = NULL;
}
5.实现接口函数。由于本应用仍然保持msgina.dll的大部分操作,所以MyGina.dll的接口函数的实现较为简单。重点需要注意的是WlxLoggedOnSAS函数的实现。当在成功登录状态下,不管接收到什么SAS事件,该函数直接返回WLX_SAS_ACTION_NONE而不做其他处理。由于实现的函数较多(必须的18个),笔者仅列出代表性的五个,其余的依理类推。
// Winlogon.exe调用的gina dll中的第一个函数
// 使gina dll确认是否支持当前版本的Winlogon.exe
// 传递给winlogon.exe需要那个版本的接口函数
BOOL WINAPI WlxNegotiate(DWORD dwWinLogonVersion, PDWORD pdwDllVersion)
{
// 直接调用从msgina.dll中导入的函数
return theApp.MyWlxNegotiate(dwWinLogonVersion,pdwDllVersion);
}
// 初始化,winlogon.exe向gina dll传递需要版本的接口函数分配表
BOOL WINAPI WlxInitialize(LPWSTR lpWinsta,
HANDLE hWlx,
PVOID pvReserved,
PVOID pWinlogonFunctions,
PVOID * pWlxContext
)
{
// 直接调用从msgina.dll中导入的函数
return theApp.MyWlxInitialize(lpWinsta,hWlx,pvReserved,pWinlogonFunctions,pWlxContext);
}
// 当系统处于锁定状态时,Winlogon.exe调用该函数
// 显示一些信息,如锁定者、锁定时间等
VOID WINAPI WlxDisplayLockedNotice(PVOID pWlxContext)
{
theApp.MyWlxDisplayLockedNotice(pWlxContext);
}
// 在系统关闭之前,Winlogon.exe调用该函数
// 允许gina dll处理一些系统关闭前的处理
VOID WINAPI WlxShutdown(PVOID pWlxContext, DWORD ShutdownType)
{
theApp.MyWlxShutdown(pWlxContext,ShutdownType);
}
// 当系统处于登陆成功,没有锁定的状态下
// Winlogon接收到SAS事件,于是调用该函数
// 现屏蔽所有事件,直接返回
int WINAPI WlxLoggedOnSAS(PVOID pWlxContext,
DWORD dwSasType,
PVOID pReserved)
{
return WLX_SAS_ACTION_NONE;
}
6.将MyGina.dll中实现的所有接口函数,在MyGina.def中定义导出。
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;type
TMainForm = class(TForm)
EnableBtn: TButton;
DisableBtn: TButton;
AboutBtn: TButton;
ExitBtn: TButton;
Bell1: TBevel;
Image: TImage;
procedure AboutBtnClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure EnableBtnClick(Sender: TObject);
procedure DisableBtnClick(Sender: TObject);
procedure ExitBtnClick(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
MainForm: TMainForm;implementationuses Hook;{$R *.dfm}type
// Declaration from VC++ WINUSER.H
//
PKBDLLHOOKSTRUCT = ^KBDLLHOOKSTRUCT;
KBDLLHOOKSTRUCT = record
vkCode: DWORD;
scanCode: DWORD;
flags: DWORD;
time: DWORD;
dwExtraInfo: DWORD;
end;const
LLKHF_ALTDOWN = KF_ALTDOWN shr 8;
WH_KEYBOARD_LL = 13;var
hhkNTKeyboard: HHOOK; // 钩子句柄// 低级键盘钩子回调函数
//
function LowLevelKeyboardFunc(nCode: Integer; w_Param: WPARAM;
l_Param: LPARAM): LRESULT; stdcall;
var
blEatKeystroke: Boolean;
p: PKBDLLHOOKSTRUCT;
begin
blEatKeystroke := False;
if nCode = HC_ACTION then
begin
case w_Param of
WM_KEYDOWN,
WM_SYSKEYDOWN,
WM_KEYUP,
WM_SYSKEYUP:
begin
p := PKBDLLHOOKSTRUCT(l_Param); // 进行按键过滤
blEatKeystroke := (((p^.vkCode = VK_TAB) and
((p^.flags and LLKHF_ALTDOWN) <> 0)) or
((p^.vkCode = VK_ESCAPE) and
((p^.flags and LLKHF_ALTDOWN) <> 0)) or
((p^.vkCode = VK_ESCAPE) and
((GetKeyState(VK_CONTROL) and $8000) <> 0)) or
((p^.vkCode = VK_DELETE) and
((p^.flags and LLKHF_ALTDOWN) <> 0) and
((GetKeyState(VK_CONTROL) and $8000) <> 0)));
end;
end; // End of Case
end;
if blEatKeystroke then
begin
Result := 1; // 捕获这些组合键,按键消息由自己处理,必须返回 1
Hook.ShowHookInfo; // 显示一个窗口,你可以改为自己的处理代码
end
else
// 其他的按键,交由别的线程处理(过滤)
Result := CallNextHookEx(0, nCode, w_Param, l_Param);
end;procedure TMainForm.AboutBtnClick(Sender: TObject);
begin
Application.MessageBox(
PChar('Windows NT 键盘钩子演示程序'#13#10#13#10'作者:Phoenix2000,2001年7月。'),
'关于本程序', 0);
end;procedure TMainForm.FormCreate(Sender: TObject);
begin
hhkNTKeyboard := 0; // 钩子句柄初值
end;procedure TMainForm.EnableBtnClick(Sender: TObject);
begin
// 挂上键盘钩子
//
hhkNTKeyboard := SetWindowsHookEx(WH_KEYBOARD_LL,
LowLevelKeyboardFunc,
HInstance, 0);
if hhkNTKeyboard <> 0 then
Application.MessageBox('系统键盘钩子已经启动了!', '信息', 64)
else
Application.MessageBox('无法启动系统键盘钩子!', '错误', 16);
end;procedure TMainForm.DisableBtnClick(Sender: TObject);
begin
// 解除键盘钩子
//
if hhkNTKeyboard = 0 then
Application.MessageBox('系统键盘钩子已经被禁止了!', '警告', 48)
else
begin
UnhookWindowsHookEx(hhkNTKeyboard); // 卸载钩子
hhkNTKeyboard := 0;
Hook.CleanHookForm; // 此行代码与钩子无关,不要误解,是我自己的窗体清除
Application.MessageBox('成功卸载系统键盘钩子!', '信息', 64)
end;
end;procedure TMainForm.ExitBtnClick(Sender: TObject);
begin
Close;
end;procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
CanClose := (hhkNTKeyboard = 0);
if not CanClose then
Application.MessageBox('请先卸载系统键盘钩子,然后再退出本程序!', '警告', 48);
end;procedure TMainForm.FormDestroy(Sender: TObject);
begin
if hhkNTKeyboard <> 0 then
begin
UnhookWindowsHookEx(hhkNTKeyboard);
hhkNTKeyboard := 0;
end;
Hook.CleanHookForm;
end;end.
Var
temp:integer;
begin
SystemParametersInfo(Spi_screensaverrunning,1,@temp,0);
end;
当你要恢复功能键时用以下代码:
Var
Temp:integer;
begin
SystemParametersInfo(spi_screensaverrunning,0,@temp,0);
end;
厉害…………
学习ing ……
http://www.iligia.com/public/download/tkhotkey/ligia_tkhotkey_source.rar
记得给分
你看了,如果还不会,那就不怪我了
http://www.eping.net
或者//作者 :韦覃武,jiangsheng//网上呢称:BCB_FANS(四大名捕之追杀令)(此为CSDN和www.driverdevelop.com之帐号)jiangsheng(此为CSDN帐号)//E-Mail :[email protected]//日期 :2002-10-20//2002-11-5 jingsheng修改//功能 :在2000下屏蔽Ctrl + Alt + Del组合键。(在Windows 2000 Professional SP3// 中文版平台下面测试通过)//原理 :采用远程线程注入技术,装载一个DLL到Winlogon进程,然后截获SAS窗口的窗// 口过程,接管WM_HOTKEY消息,以达到屏蔽Ctrl + Alt + Del之目的。//开发语言:Borland C++Builder 5.0 Patch2,Visual C++ 6.0 SP5//技术比较:关于在2000下面如何屏蔽Ctrl + Alt + Del组合键,一种常被提到的解决方法就// 是使用自己写的GINA去替换MSGINA.DLL,然后在WlxLoggedOnSAS里边直接返回// WLX_SAS_ACTION_NONE。嘿嘿,说到底这并不是真正地屏蔽了这个组合键,只是// 直接返回WLX_SAS_ACTION_NONE时,Winlogon进程又自动从"Winlogon"桌面切换// 回原来的"Default"桌面了,而不是显示安全对话框,所以看起来被屏蔽了:),// 使用那种方法明显地看到桌面在闪烁!但是使用本文的方法时,你不会看到任// 何闪烁!//鸣谢 :www.driverdevelop.com上的icube和lu0。//版权 :转载请注明原作者:)//---------------------------------------------------------------------------#include "stdafx.h"#include <tlhelp32.h>#include <lmerr.h>#include "Hook.h"//add by jiangsheng 2002-11-5#include "TaskKeyMgr.h"#include "Wrappers.h"//复制自MSDN杂志Windows XP Escape from DLL Hell with Custom Debugging and Instrumentation Tools and Utilities的代码extern BOOL Is_Terminal_Services () ;//复制自Platform SDK文档: Windows System Information /Verifying the System Version//end add by jiangsheng 2002-11-5//---------------------------------------------------------------------------//错误代码格式化函数//replaced by jiangsheng 2002-11-5//from Q149409 HOWTO: Get Message Text from Networking Error CodesCString __fastcall SysErrorMessage(DWORD dwLastError ){CString strRet(_T("Unknown error"));HMODULE hModule = NULL; // default to system sourceLPSTR MessageBuffer;DWORD dwBufferLength;DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_IGNORE_INSERTS |FORMAT_MESSAGE_FROM_SYSTEM ;//// If dwLastError is in the network range,// load the message source.//if(dwLastError >= NERR_BASE && dwLastError <= MAX_NERR) {hModule = LoadLibraryEx(TEXT("netmsg.dll"),NULL,LOAD_LIBRARY_AS_DATAFILE);if(hModule != NULL)dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE;}//// Call FormatMessage() to allow for message// text to be acquired from the system// or from the supplied module handle.//if(dwBufferLength = FormatMessageA(dwFormatFlags,hModule, // module to get message from (NULL == system)dwLastError,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language(LPSTR) &MessageBuffer,0,NULL)){//// Output message string on stderr.//strRet=CString(MessageBuffer,dwBufferLength);//// Free the buffer allocated by the system.//LocalFree(MessageBuffer);}//// If we loaded a message source, unload it.//if(hModule != NULL)FreeLibrary(hModule);return strRet;}//end replaced by jiangsheng 2002-11-5//---------------------------------------------------------------------------#ifdef UNICODELPCSTR LoadLibraryFuncStr = "LoadLibraryW";LPCSTR GetModuleHandleFuncStr = "GetModuleHandleW";#elseLPCSTR LoadLibraryFuncStr = "LoadLibraryA";LPCSTR GetModuleHandleFuncStr = "GetModuleHandleA";#endifLPCSTR FreeLibraryFuncStr = "FreeLibrary";LPCSTR GetProcAddressFuncStr = "GetProcAddress";LPCSTR GetLastErrorFuncStr = "GetLastError";//---------------------------------------------------------------------------//removed by jiangsheng 2002-11-5//const char* const RemoteDllName = "RemoteDll.Dll";//end removed by jiangsheng 2002-11-5LPCTSTR szRemoteProcessName = "Winlogon.exe";typedef HINSTANCE (WINAPI *PLOADLIBRARY)(LPCTSTR );typedef BOOL (WINAPI *PFREELIBRARY)(HINSTANCE);typedef HMODULE (WINAPI* PGETMODULEHANDLE)(LPCTSTR );typedef PVOID (WINAPI* PGETPROCADDRESS)(HINSTANCE,LPCSTR);typedef DWORD (WINAPI* PGETLASTERROR)(VOID);BOOL __fastcall EnablePrivilege(LPCTSTR lpszPrivilegeName,BOOL bEnable);DWORD __fastcall GetPIDFromName(LPCTSTR lpszProcName);//---------------------------------------------------------------------------typedef struct{PLOADLIBRARY pfnLoadLibrary;PGETLASTERROR pfnGetLastError;TCHAR szDllName[1024];DWORD dwReturnValue;} INJECTLIBINFO;typedef struct{PFREELIBRARY pfnFreeLibrary;PGETMODULEHANDLE pfnGetModuleHandle;PGETLASTERROR pfnGetLastError;DWORD dwReturnValue;TCHAR szDllName[1024];} DEINJECTLIBINFO;//---------------------------------------------------------------------------//远程线程,用来装载DLLstatic DWORD WINAPI ThreadFuncAttach(INJECTLIBINFO *pInfo){HINSTANCE hDll=NULL;pInfo->dwReturnValue = 0;hDll = (HINSTANCE)pInfo->pfnLoadLibrary(pInfo->szDllName);if(hDll == NULL)pInfo->dwReturnValue = pInfo->pfnGetLastError();return((DWORD)hDll);}//---------------------------------------------------------------------------//占位函数,用来计算ThreadFuncAttach的大小static void AfterThreadFuncAttach(void){}//---------------------------------------------------------------------------//远程线程,用来卸载DLLstatic DWORD WINAPI ThreadFuncDetach(DEINJECTLIBINFO *pInfo){HINSTANCE hDll = NULL;BOOL bResult=FALSE;BOOL bHasFoundModule = FALSE;pInfo->dwReturnValue = 0;//意味成功,如果这个值不是0,则是一个错误代码。while((hDll = pInfo->pfnGetModuleHandle(pInfo->szDllName)) != NULL){bHasFoundModule = TRUE;bResult = pInfo->pfnFreeLibrary(hDll);if(bResult == FALSE){pInfo->dwReturnValue = pInfo->pfnGetLastError();break;}}if(pInfo->dwReturnValue == 0 && !bHasFoundModule){pInfo->dwReturnValue = pInfo->pfnGetLastError();}return 1;}//---------------------------------------------------------------------------//占位函数,用来计算ThreadFuncDetach的大小static void AfterThreadFuncDetach(void){}//---------------------------------------------------------------------------//修改本进程的权限BOOL __fastcall EnablePrivilege(LPCTSTR lpszPrivilegeName,BOOL bEnable){HANDLE hToken;TOKEN_PRIVILEGES tp;LUID luid;if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES |TOKEN_QUERY | TOKEN_READ,&hToken))return FALSE;if(!LookupPrivilegeValue(NULL, lpszPrivilegeName, &luid))return TRUE;tp.PrivilegeCount = 1;tp.Privileges[0].Luid = luid;tp.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0;AdjustTokenPrivileges(hToken,FALSE,&tp,NULL,NULL,NULL);CloseHandle(hToken);return (GetLastError() == ERROR_SUCCESS);}//---------------------------------------------------------------------------
ZeroMemory(&DeinjectLibInfo,sizeof(DEINJECTLIBINFO ));DeinjectLibInfo.pfnFreeLibrary = (PFREELIBRARY)GetProcAddress(GetModuleHandle("Kernel32.dll"),FreeLibraryFuncStr);DeinjectLibInfo.pfnGetModuleHandle = (PGETMODULEHANDLE)GetProcAddress(GetModuleHandle("Kernel32.dll"),GetModuleHandleFuncStr);DeinjectLibInfo.pfnGetLastError = (PGETLASTERROR)GetProcAddress(GetModuleHandle("Kernel32.dll"),GetLastErrorFuncStr);lstrcpyn(DeinjectLibInfo.szDllName,CTaskKeyMgr::strRemoteDllName,CTaskKeyMgr::strRemoteDllName.GetLength()+1);//在远程线程分配内存来存放参数pRemoteParam = VirtualAllocEx(hRemoteProcess,NULL,sizeof(DEINJECTLIBINFO),MEM_COMMIT,PAGE_READWRITE);if(pRemoteParam == NULL){MessageBox(NULL,_T("Failed to Allocate Memory at Remote Process.Err = ") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);}Ret = WriteProcessMemory(hRemoteProcess,pRemoteParam,(LPVOID)&DeinjectLibInfo,sizeof(DEINJECTLIBINFO),&dwWriten);if(Ret == 0){MessageBox(NULL,_T("Failed to Write Param to Remote Process.Err = ") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);return;}//拷贝线程体dwThreadSize = (int)AfterThreadFuncDetach - (int)ThreadFuncDetach + 1024 + sizeof(DEINJECTLIBINFO);pRemoteThread = VirtualAllocEx(hRemoteProcess,NULL,dwThreadSize,MEM_COMMIT,PAGE_READWRITE);if(pRemoteThread == NULL){MessageBox(NULL,_T("Failed to Allocate Memory at Remote Process for Thread Code.Err = ") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);return;}Ret = WriteProcessMemory(hRemoteProcess,pRemoteThread,(LPVOID)ThreadFuncDetach,dwThreadSize,&dwWriten);if(Ret == 0){MessageBox(NULL,_T("Failed to Write Thread Code to Remote Process.Err = ") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);return;}//启动远程线程HANDLE hRemoteThread;hRemoteThread = CreateRemoteThread(hRemoteProcess ,0,0,(DWORD(__stdcall *)(VOID*))pRemoteThread,(DEINJECTLIBINFO*)pRemoteParam,0,&dwWriten);if(hRemoteThread == NULL){MessageBox(NULL,_T("Failed to create remote unload thread.Err=") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);}else{CloseHandle(hRemoteThread);}//读卸载返回值Ret = ReadProcessMemory(hRemoteProcess,pRemoteParam,(LPVOID)&DeinjectLibInfo,sizeof(DEINJECTLIBINFO),&dwWriten);if(Ret == 0){MessageBox(NULL,_T("Unable to read unload return value.Err=") + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);}else{if(DeinjectLibInfo.dwReturnValue == 0){ }else{MessageBox(NULL,_T("Failed to unload .Err=")+ SysErrorMessage(DeinjectLibInfo.dwReturnValue),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);}}//恢复权限CloseHandle(hRemoteProcess);EnablePrivilege(SE_DEBUG_NAME,false);}//---------------------------------------------------------------------------//使用方法 BOOL CTaskKeyMgr::IsCtrlAltDeleteDisabled(){return bInjectFuncLoaded;} if (dwFlags & CTRLALTDEL) {if(bDisable&&!IsCtrlAltDeleteDisabled()){InjectFunc();bInjectFuncLoaded=TRUE;}if(!bDisable&&IsCtrlAltDeleteDisabled()){DeinjectFunc();bInjectFuncLoaded=FALSE;}}
Win2000和2003下有效
下载:
http://www.iligia.com/public/download/tkhotkey/ligia_tkhotkey_source.rar
这种问题
自己去看看KINGRON的猛料
或是HUBDOG的葵花宝典!