几点心得 - lhf 的窝
虚拟表格显示控件
FreeType的光栅化功能

几点心得

LiHengFeng posted @ 2009年7月21日 18:40 in 编程 with tags 多媒体定时器 DestroyWindow 服务类型 子进程 , 1771 阅读
本blog所有文章,除声明了作者外,均为原创。欢迎转载,转载请注明作者。

1.在多媒体定时器的响应函数中不能使用DestroyWindow函数。

因为多媒体定时器实际是内部开了一个线程,在该线程中调用定时器的回调函数。

而MSDN告诉我们:

A thread cannot use DestroyWindow to destroy a window created by a different thread.

所有就有上面的结论了。那么,如果确实要调用怎么办呢? 比如用多媒体定时器来控制一个窗口的生存时间,到了一定的秒数就关闭窗口。

应该用sendmessage。

 

BOOL CScreenWnd::CreateTimer(UINT uDelay)
{
        TIMECAPS tc;
       
        if(::timeGetDevCaps(&tc,sizeof(TIMECAPS)) == TIMERR_NOERROR)//查询设备能力。
        {
                m_timerRes = min(max(tc.wPeriodMin,1),tc.wPeriodMax);
               
                if(::timeBeginPeriod(m_timerRes)==TIMERR_NOERROR)//设定定时器精度。
                {
                        MMRESULT result= ::timeSetEvent(uDelay,m_timerRes,TimerProc,(DWORD)this, TIME_PERIODIC);
                       
                        if (result != NULL)//设置成功,定时器开始起作用。
                        {
                                m_timerId = (UINT)result;
                                return TRUE;
                        }
                }
        }

        return FALSE;            
}

下面是响应函数:

 

void CALLBACK CScreenWnd::TimerProc(UINT id,UINT msg,DWORD dwUser,DWORD dw1,DWORD dw2)
{
        ::SendMessage(m_pThis->m_hWnd,WM_MY_TimeTick,0,0);
       
//      if(m_pThis->m_LiveTime==0)
//      {
                //注意,这里不能直接调DestroyWindow,因为不在同一个线程中.
//      }
}

注意:WM_MY_TimeTick是一个自定义的消息。可以在响应该消息是调用DestroyWindow。SendMessage函数为什么可以成功呢,因为该函数没有要求在同一个线程中(实际上连同一个进程都没要求,可以安全的发送消息到另一个进程的窗口,很多情况下会失败是因为地址空间的关系)。它之所以不要求,是因为该函数自己会处理线程切换等事务。

 2、服务的类型和子进程的类型

 如果服务注册为非交互式的,然后在其中产生子进程。那么子进程可以使用窗口吗(即是否能是一个GUI程序)?答案是非也。

这个问题大概根窗口站(window station)相关吧。窗口站包含了桌面,桌面包含了窗口。windows将可见的窗口站命名为WinSta0,其余的窗口站都是不可见的。

除非另行指定,windows子系统将所有运行在本地系统账户下的服务与一个非可见窗口站:Service-0x0-3e7$关联起来。所有非交互式服务都共享此窗口站。

凡是指定了某个账户(非本地系统账户)的服务,都运行在一个独立的非可见窗口站中。

总结:如果是非交互式的服务,则其子进程也在同一个窗口站(该窗口站不可见)运行,因此子进程的窗口也是不可见的。

以上内容,详见《深入解析windows操作系统第4版》p221。

 3、如何屏蔽Ctrl+alt+del

简单的说,hook winlogon.exe进程中的SAS 窗口的窗口过程。在其中拦截该组合键即可。主要步骤是:

1. 打开winlogon.exe进程。这个又分为:    a.取进程id.    b.提升权限。 c.打开进程.

 2.写该进程的内存。 写入一些数据,为加载DLL做准备。

 3.创建远程线程,让winlogon加载一个dll。

4.DLL的主函数中,替换winlogon的SAS窗口过程。注意,该窗口在桌面Winlogon下,必须先打开该桌面,才能枚举窗口。

注:2,3,4也可以完全不使用dll,直接把代码写入winlogon进程,这就需要几个占位函数以便计算各函数的代码长度。

或者,使用DLL,但只是加入代码,并不在dll主函数中做hook窗口的工作。而是创建远程线程,执行该dll中的代码。

 相关的代码网上很容易找,不过自己做的话还是会碰到一些细节问题。只要基本概念有了,找到代码然后修改是很容易的。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter