TONT 42163 BOZOSLIVEHERE和TABTHETEXTOUTFORWIMPS是怎么回事?

我姓逗,叫逗你玩。

In a previous entry I discussed the story behind the functions with the funny names BEAR, BUNNY and PIGLET. But what about the ones with goofier names like BOZOSLIVEHERE and TABTHETEXTOUTFORWIMPS?

在之前的一篇文章中,我们讨论了那些被安上了有趣的名字的方法们——BEAR(小熊)、BUNNY(小兔)和PIGLET(小猪)。那么那些名字看起来傻乎乎的方法——例如BOZOSLIVEHERE(这家伙住这儿)和TABTHETEXTOUTFORWIMPS(给懦夫用的将文本TAB出去的方法)又是怎么回事呢?

For this, you need a deeper history lesson.

要说清这件事,首先你要对历史有更深刻地了解。

Back in the old days of real-mode Windows, all callback functions had to be exported. This was necessary for complicated technical reasons I may bother to explain if anybody really cared but I doubt anybody does any more. So the window procedures for all of the standard window classes (edit controls, list boxes, check boxes, etc.) were exported from USER. So too were various other callback functions like timer procedures. This was in addition to the usual collection of internal functions so USER, KERNEL and GDI could coordinate their efforts.

回到Windows还是实模式的时候,所有的回调函数都需要导出(译注:只有导出过的函数才能直接调用,未导出的函数没有函数名,调用相对复杂一些)。由于某些复杂的技术原因,这是很有必要的,虽然如果有人在乎的话我也愿意费心解释,不过大概是不存在的。总之,因为上述原因,所有与标准窗体类(编辑控件、列表框、检查框等等)相关的窗体过程都是从USER导出的,还有一些回调函数,例如计时器过程也是这种情况。这样的设计对原有的内部调用是一种补充,以便USER、KERNEL和GDI可以协同工作。

Some people reverse-engineered all these internal functions and printed books on how they worked, and as a result there were a lot of programs that actually used them. Which was quite a surprise to us because they were internal functions. And then when we wanted to redesign these internal functions (for example, to add a parameter, or if we decided that we didn’t need it any more and tried to delete it), we found that the programs stopped working.

然而有些人对这些内部调用进行了逆向工程,还出书叙述了它们的工作原理,结果有好多程序就直接用上了这些内部函数,这是我们所没有想到的,因为明明这些函数是在内部进行调用的。后来我们想对这些内部函数进行重新设计时(例如增加参数,或者认为不再需要它时尝试直接移除),发现有些应用程序直接罢工了。

So we had to put the functions back, with their old behavior. The new features we were contemplating had to be redesigned, redirected, or possibly even abandoned entirely. (If we wanted to delete a function, then the work could continue, but the old function had to stay around with its old behavior. It was basically dead code from the OS’s point of view, hanging around just because some random app or other decided to cheat and bypass the documented way of doing things.) But to teach people a lesson, they often got given goofy names.

结果我们还是得把这些(内部)函数放回去,而这些函数也仍按照原有的方式运作。由此,那些我们深思熟虑的新功能就得重新设计、重新定向,甚至完全放弃。(原本如果我们要删除一个函数,不会对工作产生什么影响,但旧函数还是得以其以前的姿态呆在那里。从操作系统的角度来看,这个旧函数就是一段已死掉的代码,还能呆在那里只是因为某个应用程序决定不走寻常路,非要不用文档描述的方式来做事。)不过,为了给这些(调用原本不该调用的内部函数的)人一个教训,开发者们给这些函数套上了傻乎乎的名字。

For example, BOZOSLIVEHERE was originally the window procedure for the edit control, with the rather nondescript name of EditWndProc. Then some people who wanted to use the edit control window procedure decide that GetWindowLong(GWL_WNDPROC) was too much typing, so they linked to EditWndProc directly. Then when Windows 2.0 (I think) removed the need to export window procedures, we removed them all, only to find that programs stopped working. So we had to put them back, but they got goofy names as a way of scolding the programs that were doing these invalid things.

比如说,BOZOSLIVEHERE原本是编辑控件的窗体过程,曾经有个没法一眼看上去就明白的名字EditWndProc。后来有人想调用编辑控件的窗体过程,又觉得GetWindowLong(GWL_WNDPROC)太费键盘,就直接链接到EditWndProc上去了。后来在Windows 2.0的时候(大概)不再需要将窗体过程导出了,于是我们就把它们(原本导出了的内部函数)全部移除了,结果发现好多应用程序停止了工作。最后我们还是将这些函数放了回去,但给它们起了个冒傻气的名字,用来斥责那些不按规矩办事的人。

Things got even worse in Windows 95, when all our window procedures were converted to 32-bit versions. The problem is that the old window procedures were only 16-bit. So we couldn’t even simply export the 32-bit window procedure under the name BOZOSLIVEHERE. We had to write a conversion function that took an illegal 16-bit function call and converted it to the corresponding illegal 32-bit function call.

到了Windows 95的时候,事情变得更糟糕了,因为所有的窗体过程都进化到了32位的版本。问题是那些旧式窗体进程函数都只有16为的版本,所以事情就不再只是将32位的窗体进程导出,然后给它扣上BOZOSLIVEHERE的名字那么简单,结果我们得写一个转换函数,拦截这些无效的16位函数调用,再把它们转换为对应但同样无效的32位函数调用。

This is just the tip of the iceberg with respect to application compatibility. I could probably write for months solely about bad things apps do and what we had to do to get them to work again (often in spite of themselves). Which is why I get particularly furious when people accuse Microsoft of maliciously breaking applications during OS upgrades. If any application failed to run on Windows 95, I took it as a personal failure. I spent many sleepless nights fixing bugs in third-party programs just so they could keep running on Windows 95. (Games were the worst. Often the game vendor didn’t even care that their program didn’t run on Windows 95!)

以上只是应用程序兼容性问题的冰山一角。真要写起来,光是(第三方)应用程序们做的坏事、以及我们为了能让这些程序继续运行所做的努力(通常与原开发者毫无关联),我大概能连着讲上几个月。这也是为什么我听到有人批评微软在升级操作系统的时候,故意让应用程序无法正常运行的指控时,会暴跳如雷的原因。要是有在Windows 95上跑不起来的应用程序,我大概会将之视为个人的败笔,毕竟我为了修正(旧版本)第三方应用程序里的bug、使其能继续运行在Windows 95上,度过了那么多不眠之夜。(尤其是游戏的情况最糟糕,因为游戏发行商根本不在乎它们的产品在Windows 95上跑不起来!)

Comments

  1. 说白了,微软给自己的程序留了内部接口,结果内部接口被野人发现并且大量野生软件使用这些内部接口。

    下一个版本微软自己用不着这些内部接口了,按思路是去掉这些内部接口,结果为了那些野人和野生软件,不仅添加新内部接口,还把旧内部接口完全保留,而且不会继续维护,内部接口直接升级成了后门。
    本身这思维就很奇葩了,不符合软件开发规范,

    不过这是微软的思维,没人会反驳。Vista里自带9x的文件大概就是从这种思维的产物。

  2. 如果你同时在 Windows 和 Linux 上做开发,并且同时接触多个不同语言不同框架的开发环境,你就不会觉得我没看懂了。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

 剩余字数 ( Characters available )

注:请不要在评论中插入任何链接,否则将自动被识别为垃圾评论,博主将完全看不到。

Notice: please DO NOT add any links in your comment, otherwise it would be identified as SPAM automatically.

*