More servicesWindows Live
HomeHotmailSpacesOneCare
 
MSN
Sign in
 
 
Spaces home  morning的记事本PhotosProfileFriendsMore Tools Explore the Spaces community

morning的记事本

淡薄以明志,宁静以致远

Public folders

Folders shared with the world
Thanks for visiting!

64 位平台中的内联汇编语言

在高级语言(如 C/C++)中使用汇编语言的能力在当今的应用性能中是十分重要的。当然,我们还可以使用内联函数(intrinsic)来替代特定的(但非所有)汇编指令。随着 64 位 Windows 操作系统(OS)的推出,越来越多的 32 位应用正在移植到 64 位。因此,当具有内联汇编语言的 32 位应用移植到 64 位环境后,它们究竟该何去何从?大多数情况下,这些应用可在 64 位操作系统上顺利运行。但是,如果您想在 64 位环境中对其进行修改或重新编译,那么您将在 Microsoft Visual Studio* 2005 上碰到问题,因为它不识别内联汇编语言。我们可以通过以下两种方法中的任意一种来解决这个问题。首先,你可以使用支持内联汇编语言的英特尔® 编译器 9.1 版或更高,对应用进行重新编译。其次,如果您想使用 Visual Studio 2005 来重新编译应用,您必须将所有具有内联汇编语言的功能转化为汇编例程,并将其存储到 asm 文件中。最后,您就可以照常对其进行重新编译了。一般来说,如果您已经具有 Visual Studio 2005,那么只需将现有的内联汇编语言功能转化为汇编例程。这可以确保其在英特尔® 编译器以及 Visual Studio 2005 上都能够正常工作。

August 26

Visual C++

 

[edit] History

Visual C++ 6.0

The predecessor to Visual C++ was called Microsoft C/C++.

  • Visual C++ 1.0, which included MFC 2.0, was the first version of Visual C++, released in 1992, available in both 16-bit and 32-bit versions.
  • Visual C++ 1.5, which included MFC 2.5, added OLE 2.0 and ODBC support to MFC. It was 16-bit only and was the first version of Visual C++ that came only on CD-ROM.
  • Visual C++ 1.52c was a patched version of 1.5, but deserves its own entry since it is the last, and arguably most popular, development platform for Microsoft Windows 3.x. It is available through Microsoft Developer Network.
  • Visual C++ 2.0, which included MFC 3.0, was the first version to be 32-bit only. In many ways, this version was ahead of its time because Windows 95, then codenamed "Chicago", was not released, and Windows NT had only a small market share. As a result, this release was almost a "lost generation". Updates available through subscription included version 2.1 and 2.2. Microsoft included and updated Visual C++ 1.5 as part of the 2.x releases up to 2.1, which included Visual C++ 1.52, and both 16-bit and 32-bit version of the Control Development Kit (CDK) were included. Visual C++ 2.x also supported Win32s development. It is available through Microsoft Developer Network. There was a Visual C++ 2.0 RISC Edition for MIPS and Alpha processors, as well as a cross-platform edition for the Macintosh (68000 instruction set).
  • Visual C++ 4.0, which included MFC 4.0, was designed for Windows 95 and Windows NT. To allow support of legacy (Windows 3.x/DOS) projects, 4.0 came bundled with the Visual C++ 1.52 installation CD. Updates available through subscription included Visual C++ 4.1, which came with the Microsoft Game SDK (later released separately as the DirectX SDK), and Visual C++ 4.2. 4.2 did not support Windows 3.x (Win32s) development. This was the final version with a cross-platform edition for the Macintosh available and it differed from the 2.x version in that it also allowed compilation for the PowerPC instruction set.
  • Visual C++ 5.0, which included MFC 4.21, was a major upgrade from 4.2.
  • Visual C++ 6.0 (commonly known as VC6), which included MFC 6.0, was released in 1998. The release was somewhat controversial since it did not include an expected update to MFC. Visual C++ 6.0 is still quite popular and often used to maintain legacy projects. There are however issues with this version under Windows XP, especially under the debugging mode (ex: the values of static variables do not display). The debugging issues can be solved with a patch called the "Visual C++ 6.0 Processor Pack" downloadable from http://msdn2.microsoft.com/en-us/vstudio/aa718349.aspx; This page stresses that Users must also be running Windows 98, Windows NT 4.0, or Windows 2000.'
  • Visual C++ .NET 2002 (known also as Visual C++ 7.0), which included MFC 7.0, was released in 2002 with support for link time code generation and debugging runtime checks, .NET 1.0 and Visual C# and Managed C++. The new user interface used many of the hot keys and conventions of Visual Basic, which accounted for some of its unpopularity among C++ developers.
  • Visual C++ .NET 2003 (known also as Visual C++ 7.1), which included MFC 7.1, was released in 2003 along with.NET 1.1 and was a major upgrade to Visual C++ .NET 2002. It was considered a patch to Visual C++ .NET 2002 and shipped for minimal cost to owners of that version. This is the last version to support Windows 95 as a target.
  • eMbedded Visual C++ was used to develop for the Windows CE operating system. eMbedded Visual C++ was replaced as a separate development environment by Microsoft Visual Studio 2005.
  • Visual C++ 2005 (known also as Visual C++ 8.0), which included MFC 8.0, was released in November 2005. This version supports .NET 2.0 and dropped Managed C++ for C++/CLI. It also introduced OpenMP. With Visual C++ 2005, Microsoft also introduced Team Foundation Server. Visual C++ 8.0 has problems compiling MFC AppWizard projects that were created using Visual Studio 6.0, so maintenance of legacy projects can be continued with the original IDE if rewriting was not feasible.
  • Visual C++ 2008 (known also as Visual C++ 9.0) was released in November 2007. This version supports.NET 3.5, and it is currently the latest stable release.

又一次人肉搜索

今天又进行了一次较大规模的人肉搜索,目标是VC4.2/5.0.
 
今天上午,,在整理近期的工程,有不少实验性质的工程,整理过程中发现mozilla的js组件的源代码,这个以前曾看过readme和接口的部分内容,没认真看,联想到近期可能需要集成这样一个脚本引擎,就尝试打开看看.由于安装了VC2003,mdp的文件图标很醒目,所以直接打开了js.mdp,很遗憾,VC2003提示无法转换,于是用绿色版的VC6试试,依然是无法转换.然后认真读完readme,其中提到该文件可以用VC4.2/5.0打开,后来证明了firefox的团队估计是在原来VC4.2工程的基础上以MAK的语法进行的修改,这样VC IDE就不再能直接打开了,估计用make类工具能直接执行编译.由于readme提示4.2/5.0可以打开,所以第一个反应是,立刻去下载一个4.2,因为我本身也想看看更早期的VC的一些特性.
 
用几个关键字在百度,google搜了几页,没有结果,于是在完美版主群发起人肉搜索,版主糊涂也加入搜索,搜了很久,还是没有,于是把这个需求发到了看雪论坛,希望看雪的弟兄有这些早期版本VC,同时也向我所在的几个群都发了寻求VC4.2/5.0的内容.然后继续google搜索.糊涂通过emule找到了几个VC5的源,但是很不稳定,所以暂时先下,同时继续搜索.这时糊涂想到以前曾经帮忙在微软订阅页面下载过VBASDK的朋友,终于,成功下载到了VC4.2.兴高采烈的安装完4.2,结果...还是提示无法转换!难道4.2需要sp,搜了一下,4.2似乎没有sp,难道需要5.0?开始找5.0.但是半天也还是没什么收获.一方面糊涂继续找5.0,我则建立同名的工程,对比js中工程的差异.没发现什么区别.然后随意添加了几个c文件.由于工程行数很多,用beyondcompare对比了很久也没发现什么不妥之处.用最笨的办法,把认为显然能被IDE接受的部分内容复制到新的工程文件中.终于发现js工程中source file描述块包含条件判断,而我用IDE直接生成的工程文件则没有类似语句.于是删掉相关的所有语句,终于能在VC4.2中打开了!
 
不过使用4.2的过程中发现老版本和vc6还是有很大差异的.考虑到现在都这么难找VC4.2/5.0,那么以后估计更难找了.网络里看到找VC5很多都是2002及其以前的.决定把VC5也收藏到手.看雪的一个弟兄从一张很老的盗版碟中拷贝出了部分vc5安装文件.收到后,立马进行安装,但是一堆的提示文件无法拷贝,中途退出安装,直接进入安装文件目录,尝试运行IDE,运气不错IDE核心部分估计没损坏,成功打开IDE.联想到vc5 sp3中包含了大量文件,将其与原始安装程序合并,应该可以弥补许多文件.合并后安装,少了大约200个左右文件,显然,用来编译时肯定不行了.残缺不美.
 
晚上,一个群里的一个朋友说有原版ISO,但是家里不是宽带,不方便传给我.遗憾.还是google,但是google了一个晚上,依然没有.期间尝试搜索了国内各高校的ftp.很遗憾,也没能找到,找出来的都是vc6,vc2003,vc2008(很奇怪,VC2005很少,或许vc2008是最新推出的,所占比例较高,而vc6/2003应该经典版本)
 
把splash贴上来秀秀
4.2
image
5.0
image
6.0
image
 
4.2的CD中各组件都是独立目录的,可以说几乎无集成这个概念,包括stl也是单独目录,帮助是内嵌了一个浏览界面.这一版还不支持滚轮,呵呵
5.0 很接近6.0,帮助和4.2一样,但是增加了infoview工具条,快速查询所需信息,这版支持滚轮了.这个版本的启动画面很漂亮,VS2003的早期测试版本的启动画面也是这个哦.估计是安装盘损坏严重,帮助系统只能看索引,所有内容都看不了
6.0 帮助系统已经独立出来,称为msdn库,IDE总的和5.0相差不多,细小功能增强.
August 25

奥运上看到最让人心痛的画面

伊拉克的二手跑鞋与国奥数十万的LV包.
clip_image001clip_image002

clip_image0031.jpg (62.58 KB)

2008-8-25 12:49

国足奢侈装备
clip_image001[1]clip_image004

clip_image003[1]2.jpg (41.13 KB)

2008-8-25 12:49

伊拉克运动员在北京奥 运会赛艇比赛中,身上穿的旧衣服,两人穿的衣服也不统一.
clip_image001[2]clip_image005

clip_image003[2]3.jpg (102.32 KB)

2008-8-25 12:49

达娜穿在训练中着从约旦二手市场"淘"来的训练鞋.
昨日《足球》封底那篇《一边是友情,一边是爱情》,伊拉克运动员的二手跑鞋和明显洗得起毛的比赛服不能不让我唏嘘。央视频道播出了对伊拉克女子短跑选手黛娜·侯赛因的采访之后,中国人被这位姑娘感动了,她是穿着从约旦二手市场淘回来的旧跑鞋跑到北京的。而另一组照片在网上热传,已经结束了奥 运赛程的伊拉克赛艇选手,他们的比赛服,不仅已经洗得发毛,而且明显还不是同一个牌子.
而我们亲爱的国奥们,崔鹏、韩鹏、周海滨的“奢华装备”,动辄十万元以上的LV旅行包、随便在脑袋上一扣就是几千块钱的Gucci帽子……网友狂呼被雷倒了。其实这些都算不了什么,中国职业足球运动员的富豪日子,早就不是什么新闻。

August 23

极限浏览如何用英语描述呢?

极限:意取 自由浏览,功能细致完美
浏览:当然是 浏览器了.
 
那么如何用一个容易记容易念的英语来描述呢?

中国的无知网民还真不是少数

令人乍舌的支持番茄花园的言论,或许这些人不明白当法不存在时,首先就是这群人受到侵害.
August 21

CNNIC迫使域名持有者"捐出"200多个中国奥运选手域名

新闻来源:新浪科技
据中国互联网络信息中心(CNNIC)刚刚透露,民间近期悄然掀起一波奥运运动员域名捐赠热潮,截至目前已有域名持有者捐出200多个中国奥运选手域名,其中不乏冠军选手的域名,这种捐赠现象在奥运史上罕见。本次捐赠域名中的奥运冠军 : 吴敏霞、火亮、陈艳青、黄旭、陈一冰、王鑫、陈若琳、郭跃、王峰、刘子歌、金紫薇 、庞伟、邹凯、唐宾。

  据了解,游泳、跳水、举重、体操、羽毛球、射击、足球等多个项目奥运运动员的域名都在此次捐赠名单内,其中有黄旭这样参加了三届奥运会拿过两个奥运金牌的“三朝元老”的奥运冠军的域名huangxu.cn,也包括刘子歌等新奥运冠军的域名liuzige.cn。

此前CNNIC曾发出呼吁,希望在北京奥运会开幕前注册运动员姓名域名的注册者,将域名捐赠给相应运动员,用于中国奥运冠军的网络标识,这一呼吁得到用户积极响应。之前,国家体育总局也曾提前注册奥运冠军域名。

由于我国公民的重名现象非常普遍,不少奥运冠军的“.中国”域名和英文CN域名在本届奥运会开幕前就被注册使用。也有舆论认为这些人注册冠军域名只为投资转卖,此次奥运冠军捐赠人的义举让这种看法不攻自破。

据悉,此次域名捐赠呈现三个鲜明特点:捐赠数量众多、捐赠与本人重名的域名和捐赠正在使用的域名。有随机调查显示,公众普遍希望国家体育总局能尽快把运动员的域名应用起来,让这些域名早日发挥其应有的作用。

  附:本次捐赠域名中的奥运冠军

吴敏霞、火亮、陈艳青、黄旭、陈一冰、王鑫、陈若琳、郭跃、王峰、刘子歌、金紫薇 、庞伟、邹凯、唐宾。

August 20

洪磊口述:番茄花园如何捆绑流氓软件月入十万

新闻来源:新浪科技 作者:张朝阳(搜狐)
在软件产业、PC行业及互联网等领域引发了轩然大波。20日下午,洪磊的好友郑朝辉向新浪科技独家提供了一段他和洪磊聊天的录音。这段录音录于2006年9月、长度为27分钟。郑朝辉说,这段录音原本是用于他所在的第一万维网(北京神州商通网络科技公司)内部交流学习,现在洪磊遇到困难,他愿意独家授权新浪科技将它公诸于众。

根据我国的法律,未经许可修改他人软件,如果没有因此获利,定罪较为困难。番茄花园在其网站上的版权声明中也表示,他们并不提供任何出售光盘,完全供用户免费下载。一些用户为洪磊喊冤,觉得番茄花园只是盗版商的“替罪羊”,他本身并没有因此获利。用过番茄花园的用户都发现,他的操作系统捆绑了易趣插件及雅虎助手,但他是否因此获利不能妄下结论。

在这份录音资料中,洪磊自己披露,他每月因此获利10余万元,并且他自己心里清楚“让微软知道了你在利用这个赚钱,他肯定会找你”。

洪磊在录音资料中称,番茄花园在2006年时的盈利模式有三种:一,番茄花园网站的点击广告;二,洪磊通过自己的网站提供包括XP美化包在内的软件下载,这些软件中捆绑了流氓软件,洪磊因此每月获利两三万元;三,通过预装在番茄花园版的流氓软件,为广告主带去流量或注册用户,每月由此获利10余万元。

值得注意的是,本录音发生在2006年9月,已经有近两年的时间。对于互联网行业而言,两年足以发生巨变,比如后来爆发的对流氓软件的讨伐及清理,因此,此两人谈话提及的状况不代表番茄花园现状,如他的收入可能早已不是月入10万级别,可能暴涨过,也可能骤减过。

以下根据洪磊的聊天录音以第一人称的方式进行改写,话题先后顺序有调整,但均忠实于洪磊聊天的原意,小标题为编者所加。

番茄花园的成长历程

番茄花园网站和下载以前的访问量小,我都是挂在你(指郑朝辉所在的第一万维网)那里的,用的是虚拟主机,原来我是2M(兆)的带宽,后来增加到5M,要是不限制带宽,完全放开下载的话,我估计需要20M带宽,限制了就10多兆,我的软件(指番茄花园版Win XP)下载从你那撤走后,基本就只需要1到2M的带宽了。

我当时算了一下,在你那放着时,每月有3到5万独立IP,那时只靠网站的广告获得收入,非常的少,服务器都买不起,后来我和易趣及雅虎合作搞捆绑后,收入增长很快,在今年(2006年)一二月的时候,当时每月收入才2万多,我攒了10万块,我就买了一台服务器,我记得配置是英特尔奔腾4 3.0 GHz的CPU,内存是1GB的。我自己换了服务器后,发现半个月后就达到了7万独立IP。

很快,每天的独立IP就达到了15万,同时在线人数有6000人,后来达到独立IP数25万了,服务器的CPU经常负载达到90%多,CPU受不了了。我现在就把论坛服务器和下载服务器分开,我在苏州租了一个服务器放论坛程序,自己买了个服务器用作下载,放到了成都。

苏州的百兆独立带宽每月是1800块,机位费是一个月3000,打个八折,算下来是2400,全部算下来不贵。我自己买的服务器是惠普的,我记得惠普当时的网站报价是21999,我后来花了20600买的,英特尔至强双路的处理器、2GB的内存,现在的同时在线人数最高13000人,处理器占有率是45%,足够了,带宽最高达到50M,白天一般是35M。论坛的独立IP每天是3万,现在我每天全部的独立IP是40万,论坛只有下载的十分之一。

网址导航站9991.com的老板去年从上海来找我(洪磊位于江苏苏州),他们提出想全部或部分收购我的网站和软件。他们主要想要我的主业(指番茄花园版Win XP),我的网站还归我管,他们想把tomatolei.com做出一个网址导航站,他们还承诺帮我推广,我现在的独立IP是40万,他们说有信心、有能力做到100万甚至更高,翻几倍,但我的网站不能涉足其他的内容了。他们愿意每月付我4万,一直付24个月,然后整个公司30%股份归我,他们要70%。我当时没答应。他们后来又找我,4万直接变8万,就是每月给我8万,其他条件不变。我后来还是不愿意,就算第三年每月能拿50万,我的网站不归我全权管理了,这不是我想要的。

现在我每月有十几万的收入,主要来自主业(即番茄花园版XP),XP美化包每月有两三万,网站点击广告带来的收入很少。


做论坛赚不了钱

你问我现在做什么能赚钱,比较难说,我觉得,要做大的话,还是得争取人气,争取用户。就像迅雷,前段时间有人对他们投资3000万美金,他就是掌握了用户,提供免费服务,有很好的人气,还有你像51.com,刚开始做的时候亏了很多钱,后来开始有收入,比如提供类似腾讯那样的衣服啊,靠这些可以收费。51.com还给一些大公司做广告,像卓越网啊,易趣网,你带去流量或消费,都可以获得收入。51现在有280万独立IP,每月可以赚200万。

我觉得做论坛赚不了钱。论坛主要靠广告获得收入,我发现娱乐的广告点击量最多,大旗网你知道吗,他就是提供一些新闻、图片、搞笑类的东西,人气很好,我40万的独立IP,每天点击次数1万到1万五,每个点击一毛一,每天将近200块的收入。如果是电影广告,40万的独立IP,就只有三千人点击,相差五倍。电影的广告点击率0.9-1%左右,我以前也就是网上注册广告联盟,然后放代码到网站上。

我现在的论坛,每天3万独立IP,1200人同时在线,平均150人点击,每千次40块钱,每天也就十几块钱,就算你放4个广告商的广告,每天也就五六十块钱收入,一月算下来才一千多块钱。

捆绑流氓软件月入10余万元

我现在每月的收入中,软件(指番茄花园版XP)有十几万块,网站的收入只有两三万。这里面不光是XP,我自己下载网站里面也有一些打包的软件,比如XP美化包,里面都有捆绑,这些都是默认安装的。这个美化包其他下载站也有转发,他每天的下载量很大的,每天有5000人次的下载。

这些默认安装的软件,我现在就是雅虎助手和易趣网的插件,全部都是他们找我的,最开始是3721原来负责软件的找我,想看看捆绑的效果,后来是四川一家公司,他们是易趣的代理,最开始我也只是抱着试试看的心里,效果一个星期就出来了,并且是越来越好,越来越好。

我现在的易趣插件,每天能给我带来70个用户注册。易趣它是按效果付费,用户注册了才算有效。雅虎助手的价格是搜索1000次给10块钱,全球那么多番茄花园XP都是我做的,日积月累,现在一年半的时间,差不多就是现在每月10多万的收入。

自称并非行业老大

全球那么多盗版XP,很多都是我做的,我做了一年半的时间,日积月累,我自己之前都没有想到有这么多人用,说白了,就是XP光盘。有人说看到一个小县城卖盗版光盘那里都有番茄花园版XP卖。

番茄花园的名气比较大,其实我的量不是最大的,电脑公司装机版比我的量还要大。

他(指电脑公司装机版XP作者“donghai”)在做捆绑插件之前,只从别人那里拿到过两次钱,每次200块,后来他看我做了捆绑后,效果非常不错,来问我,我介绍他做易趣,他拉到一个用户我也有1块钱的提成。

他做三个月,量就比我大了,现在他每天为易趣带去100个注册用户,每月就这一项收入3万块,我做了一年半,现在每天才70个易趣注册用户,他的雅虎的搜索量也比我大,所以他的装机量比我大。

微软“管不了”

有一次我接到一个律师信,说我论坛一个帖子,是卖番茄花园版XP软件的,60块钱一套,他们就发律师信过来,说出售介质类的光盘是不允许的,叫我删除,我后来就删除了,他们还说谢谢合作,大概是说谢谢我配合他们的合作。在此之前,微软并没有找过我。

其实微软现在也知道很多人修改他的东西,他没有去管,其实也管不了。

我今天讲的这些数据不能对其他人说,因为第一别人会眼红,第二,让微软知道了你在利用这个赚钱,他肯定会找你的。
 
 
 
================================相关文章================================
电脑公司版:
 

很不错的QQ2009Preview3

1.安装时可以选择是否将聊天记录保存在哪里.这很方便,对于TX的开发人员来说几乎没有任何额外的工作量却带来很大的方便.毕竟现在XP还是主流,将用户资料放在程序目录中还是比放在我的文档方便.当然,vista下的话由于系统的缘故,放入我的文档或者个人数据目录应该是推荐的
2.传统登录界面,比起MSN风格的一长条还是方便许多,因为这样界面元素主要就是帐号输入和密码输入,没有太多的多余的(或者说不常用的)东西
 
QQ2009 Preview3公测:
August 19

番茄花园作者被抓了

呵呵,我不是任何ghost系统(也指代其他二次封装系统)的用户,我喜欢用原版的系统,毕竟原版系统从微软出来后没有再次加工,安全性和稳定性都更为可靠.
虽然各ghost系统都在不断宣称XX新的封装技术,但是我想没有人比微软更了解windows了吧.
我尤其讨厌修改主页和擅自增加BHO的东西,我很讨厌一键还原(估计以后只要说起讨厌的东西,我都不会遗漏它的,咬牙切齿)
 
如果说真正为用户方便,为用户安全着想的人,是不会做Ghost系统的,因为硬件的兼容性等在修改后往往会成问题,早些年Ghost系统无法正常关机就是一个例子.做二次系统的人可谓流氓精灵,为什么这么说呢,如果推广软件,尝试在正常的系统中安装,这需要用户额外的去安装,这其中存在用户的认知度,品牌,杀毒软件等层层检查,而ghost系统则预安装了各类应用软件(只要你装了系统,它们就在了),这其中不乏默认首页改为一些导航站,搜索引擎也被篡改,各类插件,各类软件厂商付费的合作推广,说白了,看似方便的Ghost系统成了一些人手中的推广平台(难怪孙雨要把共软网络叫做 共享软件平台了).
 
番茄花园某版本系统的说明中的一段原话:
番茄花园版都集合了一搜搜索条和易趣图标,是为了番茄花园
的发展而特别添加的,如果你不喜欢2个东西都可以在添加删除
程序里面完全可以卸载,或者选择装里面的原版系列,没有任
何其他信息,当然也可以不要下载和使用番茄花园系统!

貌似这其中隐含的说明了,如果你要用番茄花园打包的系统就必须接受所集成的插件,如果说珊瑚虫的插件是给你美酒的同时递给你毒药,当然,你可以选择不服下毒药,而番茄花园则是直接在给你的美酒中加入毒药,然后在杯底放了解药,给你解毒的可能(但是据我所知,许多初级用户是不知道何为控制面板的).

看到一段感言,甚为郁闷

如往常一样,逛看雪,发现一篇程序员的感言.
 
 
相比起这位兄弟,貌似我更郁闷,不知道哪年可以达到他几年前的收入水平,悲伤
不过,我比他年轻几岁,努力吧
August 17

安静真好

论坛终于越来越清净了,真好!

当初,写fineplus只是为了很方便的修改托盘图标,去掉广告,当然,这是由于我当时在使用QQ,并觉得QQ有些不爽,又没符合自己需要的工具.时过境迁,QQ不用了,还是主要用MSN,自然QQ的工具也不可能再有新的了.也有许多相当执着的朋友,当FP不再支持新版QQ时,努力去修改它,使其尽量完美的支持新版,还有一些人,干脆自己做辅助工具.不管怎么说,这些朋友的精神都是值得肯定的,但是执着同时,最好应注意自己的学业和工作,毕竟那只是一时兴趣,切莫花费太多的时间.

当然,MSN越来越好用了,QQ终归是要被抛弃的,MSN配合Live Plus!还是挺不错的.不过,plus!还是有些功能不爽的,而且,其实我也只要用到它的加强的聊天记录保存这功能,其他功能用不到,看来找个时间自己写一个得了.

挂钩 NtResumeThread 实现全局Hook

创建时间:2008-05-25
文章属性:原创
文章提交:BITS (zhouzhenster_at_gmail.com)
挂钩 NtResumeThread 实现全局Hook
zhouzhenster@gmail.com
zhouzhen[E.S.T]
挂钩一直是Hack 编程中永恒的主题,基本高级的Rootkit 程序多多少少都会使用Hook 技术。
似乎Hook 都被讲烂了,不论是Ring3 的还是Ring0 的网上都有例子。Ring0 的毋庸置疑当然
是全局的了,这里说说ring3 的全局hook。Ring 3 有Ring 3 的优势,稳定是压倒一切的,
因此Mcafee 和其他一些商业的安全软件都还是使用了Ring3 的Hook 技术,无论如何用户是
无法接受蓝屏和死机的。
感兴趣的可以装个Rootkit unhooker 自己看看。 :)
1. 以往的Ring 3全局Hook
纵观网上流行的全局Hook 程序都只用了一个Windows API, SetWindowsHookEx,此函数原型:
HHOOK SetWindowsHookEx(     
    int idHook,
    HOOKPROC lpfn,
    HINSTANCE hMod,
    DWORD dwThreadId
);
idhook   安装的钩子类型,如 WH_GETMESSAGE,WH_KEYBOARD 等
lpfn     hook procedure 的指针
hmod     包含 hook procedure DLL 的handle
dwThread 为0
使用这个这个API 时候有问题的,只能挂接系统中的所有G U I线程,换句通俗的话说就是有界面
的程序,Windows console 类的程序就无能为力了。
还有一种通过插入注册表来实现
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs
这种方法简单,但是还是只能挂钩GUI 程序,并且这个键值已经被广大HIPS 所关注,吃力不讨好。
以上两种效果不好,因此有人有开始另外的做法,枚举所有进程,插入和挂钩 NtCreateProcess
这是非常自然的想法,似乎也把问题解决了,但是仔细思考一下,就会发现很多问题。
a. 时机不对,在NtCreateProcess函数被调用时进程并没有真正被创建,我们无法执行HOOK操作,
   而当NtCreateProcess返回时,进程又已经开始运行
b. 如果是Windows console 创建的进程,你如何去监控这个调用呢?这么说似乎比较抽象,你可
   以这么理解,直接在命令行下,cmd,cmd,cmd .... 你可以监控到最后一个cmd 吗,如果只
   用SetWindowsHookEx
c. 是否正好站在了华容道,是否足够底层。
似乎很费劲
2. 分析系统创建进程过程,寻找方法
关于这方面内容,可以参考毛德操老师的两篇文章
《漫谈兼容内核之十七:再谈Windows的进程创建》
《漫谈兼容内核之二十二:Windows线程的调度和运行》
下面是他的blog 链接:
http://hi.baidu.com/fatbsd/blog
CreateProcess 是 Kernel32.dll 的导出函数。
操起WinDbg,剁了一下: Windows 2003 SP2
lkd> uf CreateProcessW
kernel32!CreateProcessW:
7c802474 8bff             mov     edi,edi
7c802476 55               push    ebp
7c802477 8bec             mov     ebp,esp
7c802479 6a00             push    0x0
7c80247b ff752c           push    dword ptr [ebp+0x2c]
7c80247e ff7528           push    dword ptr [ebp+0x28]
7c802481 ff7524           push    dword ptr [ebp+0x24]
7c802484 ff7520           push    dword ptr [ebp+0x20]
7c802487 ff751c           push    dword ptr [ebp+0x1c]
7c80248a ff7518           push    dword ptr [ebp+0x18]
7c80248d ff7514           push    dword ptr [ebp+0x14]
7c802490 ff7510           push    dword ptr [ebp+0x10]
7c802493 ff750c           push    dword ptr [ebp+0xc]
7c802496 ff7508           push    dword ptr [ebp+0x8]
7c802499 6a00             push    0x0
7c80249b e8a6ac0200       call    kernel32!CreateProcessInternalW (7c82d146)
7c8024a0 5d               pop     ebp
7c8024a1 c22800           ret     0x28
lkd> uf CreateProcessInternalW
....
7c82cf8f ff159814807c call dword ptr [kernel32!_imp__NtCreateProcessEx (7c801498)]
....
7c82daa2 ff159414807c call dword ptr [kernel32!_imp__NtCreateThread (7c801494)]
....
7c82dbdc ff158814807c call dword ptr [kernel32!_imp__NtResumeThread (7c801488)]
大概流程如下:
Kernel32!CreateProcessW
Kernel32!CreateProcessInternalW
ntdll!NtCreateProcessEx
ntdll!NtCreateThread
ntdll!NtResumeThread
因为进程创建后,Windows 必须为它创建一个主线程,然后等待操作系统调度它。
所以调用NtResumeThread的时候,就是我们Hook的最佳时机,因为此时创建进程的主要工作已经完成,
但是进程并没有调度起来,呵呵,方便干坏事啊。
3. 具体代码实现
基本思路已经清晰了,这里还几个问题。
a. NtResumeThread 函数并不是创建进程才调用,我们怎么区分出哪个是创建进程时
   调用的NtResumeThread呢?
其实现实起来不困难,先枚举系统进程一次,将系统进程中NtResumeThread 都挂钩上。每次拦截到
NTResumeThread 是判断NtResumeThread 的头几个字节是否已经被修改,如果没有则是创建新进程的调用。
b. 用什么方法Hook , IAT、Inline? 总的架构?
  这种代码写起来还是Inline Hook 来的舒服,修改函数调用头几个字节。
  枚举系统所有进程是不可避免的,因此要写个loader 将我们编写的DLL 插入系统所有进程。发现有进进程
  创建时,将DLL 插入新进程。
  下面代码演示,Hook NtQuerySystemInformation,因为篇幅等原因只有整体框架和关键代码。
  Hook 也不是不是我们这次的主要内容,感兴趣的可以参考
http://www.xfocus.net/articles/200403/681.html
c. 在多线程的环境下是否可靠?
  使用关键代码段,互斥锁,效果还可以。
Loader:
void inject(HANDLE hProcess){
char CurPath[256] = {0};
    strcpy(CurPath, "C:\\WINDOWS\\system32\\Hook.dll");
    PWSTR pszLibFileRemote = NULL;
    int len = (lstrlen(CurPath)+1)*2;
    WCHAR wCurPath[256];
    MultiByteToWideChar(CP_ACP,0,CurPath,-1,wCurPath,256);
    pszLibFileRemote = (PWSTR)VirtualAllocEx(hProcess,
                                             NULL,
                                             len,
                                             MEM_COMMIT,
                                             PAGE_READWRITE);
    WriteProcessMemory(hProcess, pszLibFileRemote,
            (PVOID) wCurPath, len, NULL);
    PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
        GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
    CreateRemoteThread(hProcess,
                       NULL,
                       0,   
                       pfnThreadRtn,
                       pszLibFileRemote,
                       0,
                       NULL);
}
void TotalInject()
{
    HANDLE         hProcessSnap = NULL;
    BOOL           bRet      = FALSE;
    PROCESSENTRY32 pe32      = {0};
    //  Take a snapshot of all processes in the system.
    EnableDebugPrivilege(1);
    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProcessSnap == INVALID_HANDLE_VALUE)
        return;
    //  Fill in the size of the structure before using it.
    pe32.dwSize = sizeof(PROCESSENTRY32);
    //  Walk the snapshot of the processes, and for each process,
    //  display information.
    if (Process32First(hProcessSnap, &pe32))
    {
        do
        {
                HANDLE hProcess;
                // Get the actual priority class.
                hProcess = OpenProcess (PROCESS_ALL_ACCESS,
                                        FALSE,
                                       pe32.th32ProcessID);
        inject(hProcess);
        CloseHandle(hProcess);
        }
        while (Process32Next(hProcessSnap, &pe32));
    }
    // Do not forget to clean up the snapshot object.
        EnableDebugPrivilege(0);
    CloseHandle (hProcessSnap);
    return ;
}
Hook.dll: 关键代码
#include "stdafx.h"
#include <stdio.h>
BOOL g_bHook = FALSE;
typedef LONG NTSTATUS;
#define STATUS_SUCCESS               ((NTSTATUS)0x00000000L)
#define STATUS_ACCESS_DENIED         ((NTSTATUS)0xC0000022L)
#define STATUS_INFO_LENGTH_MISMATCH  ((NTSTATUS)0xC0000004L)
typedef ULONG SYSTEM_INFORMATION_CLASS;
typedef ULONG THREADINFOCLASS;
typedef ULONG PROCESSINFOCLASS;
typedef ULONG KPRIORITY;
#define MEMORY_BASIC_INFORMATION_SIZE 28
typedef struct _THREAD_BASIC_INFORMATION {
    NTSTATUS ExitStatus;
    PNT_TIB TebBaseAddress;
    CLIENT_ID ClientId;
    KAFFINITY AffinityMask;
    KPRIORITY Priority;
    KPRIORITY BasePriority;
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
typedef struct _PROCESS_BASIC_INFORMATION { // Information Class 0
NTSTATUS ExitStatus;
PVOID PebBaseAddress;
KAFFINITY AffinityMask;
KPRIORITY BasePriority;
ULONG UniqueProcessId;
ULONG InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
typedef NTSTATUS (__stdcall *NTQUERYSYSTEMINFORMATION)(
  IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
  OUT PVOID               SystemInformation,
  IN ULONG                SystemInformationLength,
  OUT PULONG              ReturnLength OPTIONAL );
typedef NTSTATUS (__stdcall *NTRESUMETHREAD)(
IN HANDLE ThreadHandle,
OUT PULONG PreviousSuspendCount OPTIONAL
);
typedef NTSTATUS (__stdcall *NTQUERYINFORMATIONTHREAD)(
  IN HANDLE ThreadHandle,
  IN THREADINFOCLASS ThreadInformationClass,
  OUT PVOID ThreadInformation,
  IN ULONG ThreadInformationLength,
  OUT PULONG ReturnLength OPTIONAL);
typedef NTSTATUS (__stdcall * NTQUERYINFORMATIONPROCESS)(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL);
NTQUERYSYSTEMINFORMATION g_pfNtQuerySystemInformation = NULL;
NTRESUMETHREAD g_pfNtResumeThread = NULL;
BYTE g_OldNtQuerySystemInformation[5] = {0}, g_NewNtQuerySystemInformation[5] = {0};
BYTE g_OldNtResumeThread[5] = {0}, g_NewNtResumeThread[5] = {0};
DWORD dwIdOld = 0;
CRITICAL_SECTION cs;
NTSTATUS __stdcall NewNtQuerySystemInformation(
            IN ULONG SystemInformationClass,
            IN PVOID SystemInformation,
            IN ULONG SystemInformationLength,
            OUT PULONG ReturnLength);
NTSTATUS __stdcall NewNtResumeThread(IN HANDLE ThreadHandle,
OUT PULONG PreviousSuspendCount OPTIONAL);
void WINAPI HookOn();
void WINAPI HookOff();
BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved )
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
        {
             InitializeCriticalSection(&cs);
             char Name[MAX_PATH] = {0};
             GetModuleFileName(NULL, Name, MAX_PATH);
             // 杀杀冰刃玩玩
             if ( strstr(Name, "IceSword.exe") != NULL)
             {
                HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,
                                              0,
                                              GetCurrentProcessId());
                TerminateProcess(hProcess, 0);
                CloseHandle(hProcess);
             }
            if(!g_bHook)
            {
                HookOn();
            }
            #ifdef _DEBUG
               MessageBox(NULL, "Process Attach", "Remote Dll", MB_OK);
            #endif
        }
            break;
        case DLL_THREAD_ATTACH:
            break;
        case DLL_THREAD_DETACH:
            break;
        case DLL_PROCESS_DETACH:
        if(g_bHook)
        {
            HookOff();
#ifdef _DEBUG
            MessageBox(NULL, "Off!", "Hook Off", MB_OK);
#endif   
            DeleteCriticalSection(&cs);
        }
        break;
    }
        return TRUE;
}
BOOL EnableDebugPrivilege(BOOL fEnable) {
   // Enabling the debug privilege allows the application to see
   // information about service applications
   BOOL fOk = FALSE;    // Assume function fails
   HANDLE hToken;
   // Try to open this process's access token
   if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES,
      &hToken)) {
      // Attempt to modify the "Debug" privilege
      TOKEN_PRIVILEGES tp;
      tp.PrivilegeCount = 1;
      LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
      tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
      AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
      fOk = (GetLastError() == ERROR_SUCCESS);
      CloseHandle(hToken);
   }
   return(fOk);
}
#define ThreadBasicInformation 0
void inject(HANDLE hProcess){
    char CurPath[256] = {0};
    GetSystemDirectory(CurPath, 256);
    strncat(CurPath, "\\Hook.dll", 9);
    //strcpy(CurPath, "C:\\WINDOWS\\system32\\Hook.dll");
    PWSTR pszLibFileRemote = NULL;
    int len = (lstrlen(CurPath)+1)*2;
    WCHAR wCurPath[256];
    MultiByteToWideChar(CP_ACP,0,CurPath,-1,wCurPath,256);
    EnableDebugPrivilege(1);
    pszLibFileRemote = (PWSTR)
        VirtualAllocEx(hProcess, NULL, len, MEM_COMMIT, PAGE_READWRITE);
    WriteProcessMemory(hProcess, pszLibFileRemote,
        (PVOID) wCurPath, len, NULL);
    PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
         GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
    HANDLE hRemoteThread = CreateRemoteThread(hProcess,
                                                      NULL,
                                                      0,
                                                      pfnThreadRtn,
                                                      pszLibFileRemote,
                                                      0,
                                                      NULL);
    WaitForSingleObject(hRemoteThread, INFINITE);
    CloseHandle(hRemoteThread);
    EnableDebugPrivilege(0);
}
NTSTATUS __stdcall NewNtResumeThread(IN HANDLE ThreadHandle,
OUT PULONG PreviousSuspendCount OPTIONAL)
{
    NTSTATUS ret;
    NTSTATUS nStatus;
    NTQUERYSYSTEMINFORMATION NtQuerySystemInformation;
    NTQUERYINFORMATIONTHREAD NtQueryInformationThread = NULL;
    THREAD_BASIC_INFORMATION ti;
    DWORD Pid = 0;
    HMODULE hNtdll = GetModuleHandle("ntdll.dll");
    NtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)GetProcAddress(hNtdll,
                                                             "NtQuerySystemInformation");
    NtQueryInformationThread = (NTQUERYINFORMATIONTHREAD)GetProcAddress(hNtdll,
                                                             "NtQueryInformationThread");
    if (NtQueryInformationThread == NULL)
    {
#ifdef _DEBUG
        MessageBox(NULL, "can't get NtQueryInformationThread", "", MB_OK);
#endif   
    }
    nStatus = NtQueryInformationThread(ThreadHandle,
                                           ThreadBasicInformation,
                                           (PVOID)&ti,
                       sizeof(THREAD_BASIC_INFORMATION),
                                           NULL);
    if(nStatus != STATUS_SUCCESS)
    {
#ifdef _DEBUG
        MessageBox(NULL, "fuck failed", "", MB_OK);
#endif
    }
    Pid = (DWORD)(ti.ClientId.UniqueProcess);
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, Pid);
    if (hProcess == NULL)
    {
#ifdef _DEBUG
        MessageBox(NULL, "open process failed", "", MB_OK);
#endif
    }
    BYTE FirstByte[1] = {0};
    // check if the process has been hooked
    ReadProcessMemory(hProcess, NtQuerySystemInformation, FirstByte, 1, NULL);
    // 已经被Hook了
    if ( FirstByte[0] == 0xe9)
    {
       HookOff();
       ret = g_pfNtResumeThread(ThreadHandle, PreviousSuspendCount);
       HookOn();
       CloseHandle(hProcess);
       return ret;
    }
    // 创建新进程的调用,Hook 之
    else
    {
        HookOff();
        inject(hProcess);
        ret = g_pfNtResumeThread(ThreadHandle, PreviousSuspendCount);
        HookOn();
        CloseHandle(hProcess);
        return ret;
    }
}
NTSTATUS __stdcall NewNtQuerySystemInformation(
            IN ULONG SystemInformationClass,
            IN PVOID SystemInformation,
            IN ULONG SystemInformationLength,
            OUT PULONG ReturnLength)
{
    NTSTATUS ntStatus;
    HookOff();
    ntStatus = g_pfNtQuerySystemInformation(SystemInformationClass,
                                                SystemInformation,
                                                SystemInformationLength,
                                                ReturnLength);
    HookOn();
   return ntStatus;
}
void WINAPI HookOn()
{
    PMEMORY_BASIC_INFORMATION lpAllocBuffer = NULL;
    DWORD dwOldProtect, dwOldProtect2;
    HANDLE hProcess = NULL;
    dwIdOld = GetCurrentProcessId();
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, dwIdOld);
    if(hProcess == NULL)
    return ;
     HMODULE hNtdll = GetModuleHandle("ntdll.dll");
     g_pfNtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)GetProcAddress(hNtdll,
                                                    "NtQuerySystemInformation");
     if (g_pfNtQuerySystemInformation == NULL)
     {
         return;
     }
     g_pfNtResumeThread = (NTRESUMETHREAD)GetProcAddress(hNtdll, "NtResumeThread");
     if (g_pfNtResumeThread == NULL)
     {
         return;
     }
     EnterCriticalSection(&cs);
    _asm
    {
        lea edi,g_OldNtQuerySystemInformation
        mov esi,g_pfNtQuerySystemInformation
        cld
        mov ecx,5
        rep movsb
        lea edi,g_OldNtResumeThread
        mov esi,g_pfNtResumeThread
        cld
        mov ecx,5
        rep movsb
    }
    g_NewNtQuerySystemInformation[0] = 0xe9;
    g_NewNtResumeThread[0] = 0xe9;
    _asm
    {
        lea eax, NewNtQuerySystemInformation
        mov ebx, g_pfNtQuerySystemInformation
        sub eax, ebx
        sub eax, 5
        mov dword ptr [g_NewNtQuerySystemInformation + 1], eax
        lea eax, NewNtResumeThread
        mov ebx, g_pfNtResumeThread
        sub eax, ebx
        sub eax, 5
        mov dword ptr [g_NewNtResumeThread + 1], eax
    }
    .......
    LeaveCriticalSection(&cs);
    g_bHook = TRUE;
}
// 还原被修改的代码
void WINAPI HookOff()
{
    ......
    g_bHook = FALSE;
}
4. 参考资料
Microsoft MSDN,SDK & DDK
《Windows NT 2000 Native API Reference》
《Windows 核心编程》
《挂钩Windows API》
《如何在Windows NT中隐藏自己》
#
# EOF
#

http://www.xfocus.net/articles/200805/981.html

August 16

嫦娥一号上面的歌曲预存30首,为什么?

地面和卫星直接不能双向通讯么?很诧异
August 09

将visual studio 2005 SP1补丁整合到安装文件

Visual Studio 2005的SP1补丁已经发行一阵子了,大家应该都已经打上这个补丁了吧.但是每次在安装visual studio 2005就已经需要很长的时间了,再一打补丁,好家伙,需要的时间更长,有没有好方法让我们象当年整合window2000的SP补丁一样把VS2005 SP1补丁也整合到安装文件里呢?这样在以后安装就能节省很多的时间了.有的!

http://blogs.msdn.com/heaths/archive/2006/12/16/slipstreaming-visual-studio-2005-service-pack-1.aspx 看到整合方法如下

首先,需要大于3G的硬盘空间(解压VS2005用,实际感觉大概需要4~5G,因为后面应用补丁的时候还会占用空间),这个补丁只会应用到VS2005上,和我们的MSND是没有什么关系的.

1.解压VS2005.

首先需要把我们VS2005安装光盘内的安装文件解压在我们的硬盘上.使用如下命令:

msiexec.exe /a G:\VS\vs_setup.msi TARGETDIR=D:\VSSETUP /L*vx install.log

其中G:\VS\vs_setup.msi  G:是我的光驱盘符,这个目录是我光盘的VS2005安装文件的路径.

TARGETDIR=D:\VSSETUP 这个是指定你要解压到的位置,我指定了D:\VSSETUP 这个目录,大概5分钟左右,解压出了3.11G的文件.

2.释放补丁包.

把我们下载到的补丁文件解压出来.使用如下命令:

VS80sp1-KB926604-X86-CHS.exe /extract "E:\vspatch\"

E:\vspatch\ 是我解压到的目录.解压出一个VS80sp1-KB926604-X86-CHS.msp的文件,注意,是以msp为后缀名.

3.应用补丁.

把我们解压出来的两个文件进行整合,使用如下命令:

msiexec.exe /a D:\VSSETUP\vs_setup.msi /p "E:\vspatch\VS80sp1-KB926604-X86-CHS.msp" /L*vx patch.log

剩下的就是漫长的等待了,花费的时间大概和你安装好VS2005应用补丁的时间差不多吧.

打完补丁以后,把你VS安装目录(安装目录是指光盘的安装文件的目录,比如我的是G:\VS\)里的其他文件拷到D:\VSSSETUP里来了,但是,不要覆盖任何文件,还有.cab的压缩包也不用再拷了,刚才其实已经把cab里的东西在第一步的时候解压出来并应用补丁了.

现在,可以把这个应用补丁的版本重新做成一张你的VS2005(SP1)安装光盘了,下次进行VS2005的安装可省事了,
呵呵
我在虚拟机里用刚做好的新系统win2003安装应用过补丁的vs2005所有内容,没有问题.

 

http://www.cnblogs.com/zhuhee/archive/2007/01/05/612331.aspx

August 07

终于把系统装好了

windows 2003 R2 英文版,应该是很稳定的了。很幸运,上微软主页上看,可选硬件居然有AMD的CPU驱动,狂喜。把常用的工具装上,ghost几次(因为检查系统设置时又会发现忘掉设置的)。

最后,非常鄙视一键还原的作者,把系统的注册表,快捷方式改得乱七八糟。人品太差。进入设置界面还不忘提示一声,为了技术支持什么的是否将主页设为XX来着,一派胡言。

窗体,消息,消息过程

windows是一个使用窗口与用户进行交互的操作系统,窗口就是一个特定的区域,我们在窗口中可以使用它所提供的各类功能,这其中不乏包括点击了鼠标,按下了某些按键,甚至关机了,等等。那么操作系统如何来通知特定的窗口发生了什么事件呢, 在windows操作系统中使用了消息这个概念,无论发生什么都以消息的方式通知这个窗口(联想一下邮箱),而处理这些消息的程序,被称为窗口过程。

(可能你需要好好理解窗口,消息,窗口过程)

为了让windows下的窗口方便在一定的基础上,方便的增加功能,微软允许消息是可以用户定义的,窗体过程也可以被替换(当然,新的过程不必处理所有原来过程所处理的所有消息,否则,增加功能也太麻烦了,也是无意义的重复劳动,所以,新过程只需要处理自己感兴趣的消息,并让原来的过程来处理剩下的消息)。

让我们用通俗易懂的例子说明这个过程。现在有两队人(假设S和R队),他们要完成转达一系列消息的活动,S队每人依次发言,当然其中有很多老外,R队则负责把内容合理的整理。当S队发言时,R队依次执行下面几种可能的操作。当然游戏过程中随时可以在队伍前端增加队员,新增加的队员自然优先得到消息。(这个往队伍增加成员的过程在windows中叫做子类化)

1. 遇到它时,它直接处理完了,并且不打算后续队员继续处理,那么直接就可以告诉S队,消息已经处理了,结果是什么。

2. 它不打算处理,或不认识这个消息,那么直接让后面的来处理。

3. 它进行了处理,然后把修改了的消息告诉后面的队员,从而后面的队员处理的是修改后的信息

4. 它先不进行处理,把消息告诉后面的,但是它要求后面的处理完后,把结果告诉它,它根据情况,把修改后的结果告诉S队。

操作系统可以看作S队,不断把各类消息发给窗口,窗口就是R队,它队收到的消息进行合理的处理后返回结果给操作系统。而R队的队员就是窗口过程了,消息在窗口过程中的传递中就可能遇到前面所说的4种情况。