热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

VC实现下屏蔽Ctrl+Alt+Del键

大家知道,Ctrl+Alt+Del是Win2kNT操作系统默认的系统登录注销组合键序列,系统级别很高。在应用程序中,想要屏蔽掉该键序列的响应或得到这个按下事件,难度是相当大的。本例介绍了
大家知道,Ctrl+Alt+Del是Win2k/NT操作系统默认的系统登录/注销组合键序列,系统级别很高。在应用程序中,想要屏蔽掉该键序列的响应或得到这个"按下"事件,难度是相当大的。本例介绍了一种简单易行的方法,实现在用户登录成功后,按下Ctrl+Alt+Del不再弹出"Windows安全"对话框。需要读者朋友注意的是,本实例必须运行在Windows 2000环境下。

   一、 实现方法

  首先介绍一下Winlogon。Windows 2000/NT有三种系统状态:没有用户登录状态、用户成功登录状态以及工作站锁定状态。Winlogon是Windows 2000/NT操作系统提供交互式登录支持的组件。Winlogon有三个组成部分:可执行文件winlogon.exe,提供图形界面认证功能的动态库Gina Dll,以及一些网络服务提供动态库Network Provider Dll。参考模型如下:

VC实现Win2000下屏蔽Ctrl+Alt+Del键
参考模型

  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函数的实现进行必要的改变,不管接收到什么SAS事件,该函数直接返回WLX_SAS_ACTION_NONE而不做其他处理。

   二、编程步骤

  1、启动Visual C++6.0,新建一个项目,选择MFC AppWizard(dll),项目名输入为MyGina,按下"OK"后,选择Regular DLL with MFC statically linked,按下"Finish";

  2、使用Class Wizard重载CmyGinaApp类的InitInstance()和ExitInstance()两个函数,并注意在Stdafx.h中加入#include

  3、在MyGina.h文件中说明"extern CMyGinaApp theApp",以便于程序其他地方对theApp的引用;在类CMyGinaApp中定义成员变量(具体内容见代码部分);

  4、添加代码,编译程序。

   三、程序代码

// //////////////////////////////////////////MyGina.h : main header file for the MYGINA DLL
#if !defined(AFX_MYGINA_H__5959C4FD_1D31_4E51_B3CD_B5649C8473B7__INCLUDED_)
#define AFX_MYGINA_H__5959C4FD_1D31_4E51_B3CD_B5649C8473B7__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif
#include "resource.h" // main symbols
//定义的函数类型;
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,PWLX_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); 

class CMyGinaApp : public CWinApp
{
 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;
 public:
  CMyGinaApp();
  // Overrides
  // ClassWizard generated virtual function overrides
  //{{AFX_VIRTUAL(CMyGinaApp)
   public:
    virtual BOOL InitInstance();
    virtual int ExitInstance();
  //}}AFX_VIRTUAL
  //{{AFX_MSG(CMyGinaApp)
  // NOTE - the ClassWizard will add and remove member functions here.
  // DO NOT EDIT what you see in these blocks of generated code !
  //}}AFX_MSG
 DECLARE_MESSAGE_MAP()
};

extern CMyGinaApp theApp;
#endif 
//////////////////

#include "stdafx.h"
#include "MyGina.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////// CMyGinaApp
BEGIN_MESSAGE_MAP(CMyGinaApp, CWinApp)
//{{AFX_MSG_MAP(CMyGinaApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
////////////////////////////////////////////// CMyGinaApp construction
CMyGinaApp::CMyGinaApp()
{
 // 初始化各变量
 hMsDll = NULL;
 MyWlxNegotiate = NULL;
 MyWlxInitialize = NULL;
 MyWlxActivateUserShell = NULL;
 MyWlxDisplayLockedNotice = NULL;
 MyWlxDisplaySASNotice = NULL;
 MyWlxDisplayStatusMessage = NULL;
 MyWlxGetStatusMessage = NULL;
 MyWlxIsLockOk = NULL;
 MyWlxIsLogoffOk = NULL;
 MyWlxLoggedOnSAS= NULL;
 MyWlxLoggedOutSAS = NULL;
 MyWlxLogoff = NULL;
 MyWlxNetworkProviderLoad = NULL;
 MyWlxRemoveStatusMessage = NULL;
 MyWlxScreenSaverNotify = NULL;
 MyWlxShutdown = NULL;
 MyWlxStartApplication = NULL;
 MyWlxWkstaLockedSAS = NULL;
}

CMyGinaApp theApp;

BOOL CMyGinaApp::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");
 }
 return CWinApp::InitInstance();
}

int CMyGinaApp::ExitInstance() 
{
 if (hMsDll != NULL)
 {
  ::FreeLibrary(hMsDll);//卸载动态链接库;
  hMsDll = NULL;
 }
 return CWinApp::ExitInstance();
}
////////////////////////////////////////////消息处理函数的实现; 
#include "StdAfx.h"
#include "MyGina.h"
// Winlogon.exe调用的gina dll中的第一个函数
// 使gina dll确认是否支持当前版本的Winlogon.exe
// 传递给winlogon.exe需要那个版本的接口函数
BOOL WINAPI WlxNegotiate(DWORD dwWinLogonVersion, PDWORD pdwDllVersion)
{
 return theApp.MyWlxNegotiate(dwWinLogonVersion,pdwDllVersion);
}

// 初始化,winlogon.exe向gina dll传递需要版本的接口函数分配表
BOOL WINAPI WlxInitialize(LPWSTR lpWinsta,HANDLE hWlx,PVOID pvReserved,PVOID pWinlogonFunctions,PVOID * pWlxContext)
{
 return theApp.MyWlxInitialize(lpWinsta,hWlx,pvReserved,pWinlogonFunctions,pWlxContext);
}

// 用户登陆成功后,Winlogon.exe调用该函数启动用户外壳程序
BOOL WINAPI WlxActivateUserShell(PVOID pWlxContext,PWSTR pszDesktopName,PWSTR pszMprLogonScript,PVOID pEnvironment)
{
 return theApp.MyWlxActivateUserShell(pWlxContext,pszDesktopName,pszMprLogonScript,pEnvironment);
}

// 当系统处于锁定状态时,Winlogon.exe调用该函数
// 显示一些信息,如锁定者、锁定时间等
VOID WINAPI WlxDisplayLockedNotice(PVOID pWlxContext)
{
 theApp.MyWlxDisplayLockedNotice(pWlxContext);
}

// 当没有任何用户登陆时,Winlogon.exe调用该函数显示一些提示信息
// 可以根据用户的动作模拟SAS事件的发送
VOID WINAPI WlxDisplaySASNotice(PVOID pWlxContext)
{
 theApp.MyWlxDisplaySASNotice(pWlxContext);
}

// 当gina dll要显示一些信息时,Winlogon.exe调用该函数
// 直接返回TRUE表示信息已经显示
BOOL WINAPI WlxDisplayStatusMessage(PVOID pWlxContext,
HDESK hDesktop,
DWORD dwOptions,
PWSTR pTitle,
PWSTR pMessage)
{
 return theApp.MyWlxDisplayStatusMessage(pWlxContext,hDesktop,dwOptions,pTitle,pMessage);
 // return TRUE;
}

// Winlogon.exe调用该函数得到gina dll显示的状态信息
// 直接返回TRUE表示信息已经接收
BOOL WINAPI WlxGetStatusMessage(PVOID pWlxContext,
DWORD *pdwOptions,
PWSTR pMessage,
DWORD dwBufferSize)
{
 return theApp.MyWlxGetStatusMessage(pWlxContext,pdwOptions,pMessage,dwBufferSize);
 // return TRUE;
}

// 在试图锁定工作站之前Winlogon.exe调用该函数,判断是否可以锁定
// 直接返回FALSE表示不能锁定
BOOL WINAPI WlxIsLockOk(PVOID pWlxContext)
{
 return theApp.MyWlxIsLockOk(pWlxContext);
 // return FALSE;
}

// 在试图注销时Winlogon.exe调用该函数,判断能否注销
// 直接返回FALSE表示不能注销
BOOL WINAPI WlxIsLogoffOk(PVOID pWlxContext)
{
 return theApp.MyWlxIsLogoffOk(pWlxContext);
 // return FALSE;
}

// 当系统处于登陆成功,没有锁定的状态下 
// Winlogon接收到SAS事件,于是调用该函数
// 现屏蔽所有事件,直接返回
int WINAPI WlxLoggedOnSAS(PVOID pWlxContext,
DWORD dwSasType,
PVOID pReserved)
{
 return WLX_SAS_ACTION_NONE;
}

// 在没有任何一个用户登陆的情况下,Winlogon.exe接收到SAS事件调用该函数
int WINAPI WlxLoggedOutSAS(PVOID pWlxContext,
DWORD dwSasType,
PLUID pAuthenticationId,
PSID pLogonSid,
PDWORD pdwOptions,
PHANDLE phToken,
PWLX_MPR_NOTIFY_INFO pMprNotifyInfo,
PVOID * pProfile)
{
 return theApp.MyWlxLoggedOutSAS(pWlxContext,dwSasType,pAuthenticationId,
  pLogonSid,pdwOptions,phToken,pMprNotifyInfo,pProfile);
}

// Winlogon.exe调用该函数,通知gina dll用户注销操作
// 允许gina dll做出相应的处理
VOID WINAPI WlxLogoff(PVOID pWlxContext)
{
 theApp.MyWlxLogoff(pWlxContext);
}

// Winlogon.exe调用该函数收集有效的认证信息
// 返回TRUE表示用户被识别 
BOOL WINAPI WlxNetworkProviderLoad(PVOID pWlxContext,
PWLX_MPR_NOTIFY_INFO pNprNotifyInfo)
{
 return theApp.MyWlxNetworkProviderLoad(pWlxContext,pNprNotifyInfo);
 // return TRUE;
}

// Winlogon.exe调用该函数,告诉gina dll停止显示状态信息
// 直接返回TRUE表示信息已经删除
BOOL WINAPI WlxRemoveStatusMessage(PVOID pWlxContext)
{
 return theApp.MyWlxRemoveStatusMessage(pWlxContext);
 // return TRUE;
}

// 在屏保程序启动前一瞬Winlogon.exe调用该函数,允许gina dll同屏保程序交互
// 返回FALSE表示屏保程序不能启动
BOOL WINAPI WlxScreenSaverNotify(PVOID pWlxContext, BOOL *pSecure)
{
 return theApp.MyWlxScreenSaverNotify(pWlxContext,pSecure);
}

// 在系统关闭之前,Winlogon.exe调用该函数
// 允许gina dll处理一些系统关闭前的处理
VOID WINAPI WlxShutdown(PVOID pWlxContext, DWORD ShutdownType)
{
 theApp.MyWlxShutdown(pWlxContext,ShutdownType);
}

// 当系统要求在用户上下文中启动程序,Winlogon.exe调用该函数
// 这种情况发生在:浏览器非正常关闭需要重启或需要启动扩展的任务管理器
// 该接口gina dll可以选择性实现
BOOL WINAPI WlxStartApplication(PVOID pWlxContext,PWSTR pszDesktopName,PVOID pEnvironment,PWSTR pszCmdLine)
{
 return theApp.MyWlxStartApplication(pWlxContext,pszDesktopName,pEnvironment,pszCmdLine);
}

// 在锁定状态下,Winlogon.exe接收到SAS事件调用该函数
int WINAPI WlxWkstaLockedSAS(PVOID pWlxContext, DWORD dwSasType)
{
 return theApp.MyWlxWkstaLockedSAS(pWlxContext,dwSasType);
}

   四、小结

  本实例介绍了如何通过自定义一个DLL文件来屏蔽Windows2000下Ctrl+Alt+Del键的方法,对于读者朋友了解Windows的内幕性知识是有帮助的,当然,屏蔽Ctrl+Alt+Del键的方法不止这一种,本实例只是起一个抛砖引玉,开拓思路的作用。

推荐阅读
  • Activity跳转动画 无缝衔接
    Activity跳转动画 无缝衔接 ... [详细]
  • 深入解析C++ Atomic编程中的内存顺序
    在多线程环境中,为了防止多个线程同时修改同一数据导致的竞争条件,通常会使用内核级同步对象,如事件、互斥锁和信号量等。然而,这些方法往往伴随着高昂的上下文切换成本。本文将探讨如何利用C++11中的原子操作和内存顺序来优化多线程编程,减少不必要的开销。 ... [详细]
  • 如何使用Maven将依赖插件一并打包进JAR文件
    本文详细介绍了在使用Maven构建项目时,如何将所需的依赖插件一同打包进最终的JAR文件中,以避免手动部署依赖库的麻烦。 ... [详细]
  • 深入理解Java反射机制
    本文将详细介绍Java反射的基础知识,包括如何获取Class对象、反射的基本过程、构造器、字段和方法的反射操作,以及内省机制的应用。同时,通过实例代码加深对反射的理解,并探讨其在实际开发中的应用。 ... [详细]
  • 本文详细介绍了Oracle RMAN中的增量备份机制,重点解析了差异增量和累积增量备份的概念及其在不同Oracle版本中的实现。通过对比两种备份方式的特点,帮助读者选择合适的备份策略。 ... [详细]
  • 探讨如何在C++中,当子类实例存储在父类类型的向量中时,正确访问子类特有的成员变量或方法。 ... [详细]
  • 我们正在使用GNU Make来构建我们的系统,在makefile文件的末尾,我们通过一个名为Makedepends的包含来生成一系列的.d文件。然而,当文件被删除或移动时,依赖关系会中断,我们需要寻找一种方法来优雅地处理这种情况。 ... [详细]
  • 圣诞夜的驯鹿之谜:鲁道夫是公是母?
    野生动物专家探讨圣诞老人座驾上的驯鹿性别之谜 ... [详细]
  • 本文详细介绍了Java中的代理模式,包括静态代理、JDK动态代理和Cglib动态代理的实现方式。通过一个火车票销售系统的实例,对比分析了三种代理模式的特点及其应用场景。 ... [详细]
  • 深入解析Android Activity生命周期
    本文详细探讨了Android中Activity的生命周期,通过实例代码和详细的步骤说明,帮助开发者更好地理解和掌握Activity各个阶段的行为。 ... [详细]
  • 本教程旨在指导开发者如何在Android应用中通过ViewPager组件实现图片轮播功能,适用于初学者和有一定经验的开发者,帮助提升应用的视觉吸引力。 ... [详细]
  • 本文介绍了在解决Hive表中复杂数据结构平铺化问题后,如何通过创建视图来准确计算广告日志的曝光PV,特别是针对用户对应多个标签的情况。同时,详细探讨了UDF的使用方法及其在实际项目中的应用。 ... [详细]
  • 今天老师上课讲解的很好,特意记录下来便于以后复习。多态的简单理解*1.什么是多态性?*(1)同一个动作与不同的对象产生不同的行为*(2)多态指的 ... [详细]
  • 本文详细探讨了select和epoll两种I/O多路复用技术的内部实现原理,分析了它们在处理大量文件描述符时的性能差异,并通过具体示例代码展示了select的工作流程。 ... [详细]
  • 本文由公众号【数智物语】(ID: decision_engine)发布,关注获取更多干货。文章探讨了从数据收集到清洗、建模及可视化的全过程,介绍了41款实用工具,旨在帮助数据科学家和分析师提升工作效率。 ... [详细]
author-avatar
RAL-1314921
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有