注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

BCB-DG's Blog

...

 
 
 

日志

 
 

SimulateCtrlAltDel  

2007-07-24 10:24:11|  分类: Delphi |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

OSVERSIONINFO osversioninfo;
DWORD g_platform_id;
DWORD g_version_major;
DWORD g_version_minor;
osversioninfo.dwOSVersionInfoSize = sizeof(osversioninfo);
if (!GetVersionEx(&osversioninfo)) g_platform_id = 0;
g_platform_id = osversioninfo.dwPlatformId;
g_version_major = osversioninfo.dwMajorVersion;
g_version_minor = osversioninfo.dwMinorVersion;

// IsWinNT - returns a bool indicating whether the current OS is WinNT
BOOL vncService::IsWinNT()
{
 return (g_platform_id == VER_PLATFORM_WIN32_NT);
}

// - SelectDesktop(char *)
// Switches the current thread into a different desktop, by name
// Calling with a valid desktop name will place the thread in that desktop.
// Calling with a NULL name will place the thread in the current input desktop.
BOOL vncService::SelectDesktop(char *name)
{
 // Are we running on NT?
 if (IsWinNT())
 {
  HDESK desktop;
  if (name != NULL)
  {
   // Attempt to open the named desktop
   desktop = OpenDesktop(name, 0, FALSE,
    DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
    DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
    DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
    DESKTOP_SWITCHDESKTOP | GENERIC_WRITE);
  }
  else
  {
   // No, so open the input desktop
   desktop = OpenInputDesktop(0, FALSE,
    DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
    DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
    DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
    DESKTOP_SWITCHDESKTOP | GENERIC_WRITE);
  }

  // Did we succeed?
  if (desktop == NULL) {
   vnclog.Print(LL_INTERR, VNCLOG("unable to open desktop, error=%d\n"), GetLastError());
   return FALSE;
  }
  // Switch to the new desktop
  if (!SelectHDESK(desktop)) {
   // Failed to enter the new desktop, so free it!
   vnclog.Print(LL_INTERR, VNCLOG("SelectDesktop() failed to select desktop\n"));
   if (!CloseDesktop(desktop))
    vnclog.Print(LL_INTERR, VNCLOG("SelectDesktop failed to close desktop, error=%d\n"), GetLastError());
   return FALSE;
  }
  // We successfully switched desktops!
  return TRUE;
 }
 return (name == NULL);
}

// - SelectDesktop(HDESK)
// Switches the current thread into a different desktop by desktop handle
// This call takes care of all the evil memory management involved
BOOL vncService::SelectHDESK(HDESK new_desktop)
{
 // Are we running on NT?
 if (IsWinNT())
 {
  HDESK old_desktop = GetThreadDesktop(GetCurrentThreadId());
  DWORD dummy;
  char new_name[256];
  if (!GetUserObjectInformation(new_desktop, UOI_NAME, &new_name, 256, &dummy))
                {
   vnclog.Print(LL_INTERR, VNCLOG("GetUserObjectInformation() failed\n"));
   return FALSE;
  }
  vnclog.Print(LL_INTINFO, VNCLOG("SelectHDESK() to %s (%x) from %x\n"), new_name, new_desktop, old_desktop);
  // Switch the desktop
  if(!SetThreadDesktop(new_desktop))
                {
   vnclog.Print(LL_INTERR, VNCLOG("unable to SetThreadDesktop(), error=%d\n"), GetLastError());
   return FALSE;
  }
  // Switched successfully - destroy the old desktop
  if (!CloseDesktop(old_desktop)) vnclog.Print(LL_INTERR, VNCLOG("SelectHDESK failed to close old desktop %x, error=%d\n"), old_desktop, GetLastError());
  return TRUE;
 }
 return TRUE;
}

// Static routine used to fool Winlogon into thinking CtrlAltDel was pressed
void *SimulateCtrlAltDelThreadFn(void *context)
{
 HDESK old_desktop = GetThreadDesktop(GetCurrentThreadId());
 // Switch into the Winlogon desktop
 if (!vncService::SelectDesktop("Winlogon"))
 {
  vnclog.Print(LL_INTERR, VNCLOG("failed to select logon desktop\n"));
  return FALSE;
 }
 vnclog.Print(LL_ALL, VNCLOG("generating ctrl-alt-del\n"));
 // Fake a hotkey event to any windows we find there.... :(
 // Winlogon uses hotkeys to trap Ctrl-Alt-Del...
 PostMessage(HWND_BROADCAST, WM_HOTKEY, 0, MAKELONG(MOD_ALT | MOD_CONTROL, VK_DELETE));
 // Switch back to our original desktop
 if (old_desktop != NULL) vncService::SelectHDESK(old_desktop);
 return NULL;
}

// Static routine to simulate Ctrl-Alt-Del locally
BOOL vncService::SimulateCtrlAltDel()
{
 vnclog.Print(LL_ALL, VNCLOG("preparing to generate ctrl-alt-del\n"));
 // Are we running on NT?
 if (IsWinNT())
 {
  vnclog.Print(LL_ALL, VNCLOG("spawn ctrl-alt-del thread...\n"));
  // *** This is an unpleasant hack.  Oh dear.
  // I simulate CtrAltDel by posting a WM_HOTKEY message to all
  // the windows on the Winlogon desktop.
  // This requires that the current thread is part of the Winlogon desktop.
  // But the current thread has hooks set & a window open, so it can't
  // switch desktops, so I instead spawn a new thread & let that do the work...

  omni_thread *thread = omni_thread::create(SimulateCtrlAltDelThreadFn);
  if (thread == NULL) return FALSE;
  thread->join(NULL);
  //if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0) throw omni_thread_fatal(GetLastError());
  return TRUE;
 }
 return TRUE;
}

// NT only function to establish whether we're on the current input desktop
BOOL vncService::InputDesktopSelected()
{
 // Are we running on NT?
 if (IsWinNT())
 {
  // Get the input and thread desktops
  HDESK threaddesktop = GetThreadDesktop(GetCurrentThreadId());
  HDESK inputdesktop = OpenInputDesktop(0, FALSE,
    DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
    DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
    DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
    DESKTOP_SWITCHDESKTOP | GENERIC_WRITE);

  // Get the desktop names:
  // *** I think this is horribly inefficient but I'm not sure.
  if (inputdesktop == NULL)
      return FALSE;

  DWORD dummy;
  char threadname[256];
  char inputname[256];

  if (!GetUserObjectInformation(threaddesktop, UOI_NAME, &threadname, 256, &dummy)) {
   if (!CloseDesktop(inputdesktop))
    vnclog.Print(LL_INTWARN, VNCLOG("failed to close input desktop\n"));
   return FALSE;
  }
  _ASSERT(dummy <= 256);
  if (!GetUserObjectInformation(inputdesktop, UOI_NAME, &inputname, 256, &dummy)) {
   if (!CloseDesktop(inputdesktop))
    vnclog.Print(LL_INTWARN, VNCLOG("failed to close input desktop\n"));
   return FALSE;
  }
  _ASSERT(dummy <= 256);

  if (!CloseDesktop(inputdesktop))
   vnclog.Print(LL_INTWARN, VNCLOG("failed to close input desktop\n"));

  if (strcmp(threadname, inputname) != 0)
   return FALSE;
 }
 return TRUE;
}

  评论这张
 
阅读(740)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017