Day 6575 Windows 95 彩蛋音乐 Clouds.mid 的来源

这篇文章之前我居然没翻译?

原文地址:https://www.brianorr.com/blog/2010/01/14/windows-95-easter-egg-song-clouds-mid/


In early 1995, I was working at Microsoft as an intern software engineer on the Windows 95 team, and was approached to write the music for the hidden Windows 95 Easter Egg.

This ‘Easter Egg’ was tricky to find (see the instructions below), but once found it opened up a window with all the names of who worked on Windows 95, with my music as the theme.

1995 年的早些时候,我在微软公司的 Windows 95 团队中担任实习软件工程师,有人邀请我为隐藏的 Windows 95 彩蛋撰写音乐。

这个“彩蛋”不怎么好找(后附打开方式),不过只要找到了,系统就会打开一个窗口,展示所有为 Windows 95 开发做出贡献的人员名单,而它将会用我的作品作为背景音乐。

The only instructions I was given was that the music should invoke images of ‘clouds’ and feel ‘floating’ and ‘peaceful’ – this is how Windows 95 was going to be marketed. Well, and that it had to play well on all sound cards at the time. For 99.9% of computers, this meant through the Adlib synthesizer emulation of the Creative Labs Sound Blaster card (or equivalent clone). In other words – no sampled instruments, no effects – just simple FM synthesis. General MIDI at its finest.

So with that said, I really couldn’t do too much in terms of interesting instrumentation or sounds; and yes…it’s pretty funny to listen to the tune now. I’ve rendered it out using a GM sound module (which is better) but still doesn’t come close to the realism you’d expect from most computer music today.

我接到的仅有的指示是:这则音乐应囊括“云朵”的印象,并给人以“飘逸”、“平和”的感觉——而这正是 Windows 95 的市场定位。此外,它还需要能在当时所有的声卡上播放出来。对(当时)99.9%的环境来说,这意味着创新公司声霸卡(或者同类克隆)里的 Adlib 合成器模拟水平,换句话说,不许有采样乐器,不许有特殊效果,只能是简简单单的 FM 合成器音效,只能是最纯粹的 General MIDI。

由此,我在富有趣味性的乐器或音效方面大大受限,不过如今再度聆听这首旋律仍是一件乐事。我用 GM(Generan MIDI)的音效模块重新渲染了一下(略有提升),不过与当今多数的计算机音乐的真实度仍然难以相提并论。

Feel free to post comments or send me any questions. Here’s the tune:

请随意发表评论或向我提问(注:原文如此),曲子在这(注:以下内容托管在 Soundcloud 上,可能需要搬梯子):

These are the original instructions to actually see the Easter Egg in Windows 95. Note this doesn’t work in Windows 98 or above, nor under some versions of the Active Desktop under Windows 95.

以下是在 Windows 95 下调出彩蛋的原始方案。注意 Windows 98 及以上版本无效,在 Windows 95 下部分版本的 Active Desktop 下也可能不起效(译注:下面的文件夹命名一个字或一个标点也不能错,包括中间的空格也不能省略):

Create a new folder on the Desktop and name it EXACTLY like this

(在桌面上创建一个新文件夹,严格按照下列内容命名):

and now, the moment you’ve all been waiting for

Then rename it to:(然后将其改名为:)

we proudly present for your viewing pleasure

Rename this folder again to:(最后一次将其改名为:)

The Microsoft Windows 95 Product Team!

Double-click the new folder and enjoy the show!(现在双击这个文件夹,就能看到表演了!)

TONT 31753 为什么有两份『记事本』的程序文件?

原文链接:https://devblogs.microsoft.com/oldnewthing/20060328-17/?p=31753

You may have noticed that there’s a copy of Notepad in %windir%\notepad.exe and another in %windir%\system32\notepad.exe.Why two?

可能你会注意到在 %windir%\notepad.exe 和 %windir%\system32\notepad.exe 分别各有一份记事本的程序文件,为什么会这样呢?

Compatibility, of course.

当然是为了兼容性了。

Windows 3.0 put Notepad in the Windows directory. Windows NT put it in the System32 directory. Notepad is perhaps the most commonly hardcoded program in Windows. many Setup programs use it to view the Readme file, and you can use your imagination to come up with other places where a program or batch file or printed instructions will hard-code the path to Notepad. In order to be compatible with programs designed for Windows 95, there needs to be a copy of Notepad in the Windows directory. And in order to be compatible with programs designed for Windows NT, there also needs to be a copy in the System32 directory.

Windows 3.0 在 Windows 目录下放置记事本,Windows NT 则放在 System32 目录下面。记事本大概是被硬编码到程序里最多的 Windows 组件之一了,很多安装程序都调用它来展示 Readme 文件,可想而知还有多少程序、批处理文件或印刷出来的操作说明里有硬编码的记事本的路径。为了保持与为 Windows 95 设计的应用程序的兼容性,在 Windows 目录下需要有一份记事本程序的副本,同样,为了保持与为 Windows NT 设计的程序的兼容性,System32 目录下也有一份。

And now that Notepad exists in both places, new programs have a choice of Notepads, and since there is no clear winner, half of them will choose the one in the Windows directory and half will choose the one in the System32 directory, thereby ensuring the continued existence of two copies of Notepad for years to come.

如今记事本在两个位置都有一席之地,新编写的程序就可以自由选择了。鉴于没有哪一份是明显的赢家,选择 Windows 目录下那份和选择 System32 目录下的那份的程序大概是一半一半的几率,由此保持两份副本共存的做法还要一直持续下去。

TONT 32453 为什么在NTFS分区和FAT分区上,回收站文件夹的名字不一样?

原文链接:https://devblogs.microsoft.com/oldnewthing/20060131-00/?p=32453

译注:原文第一段比较长,为方便阅读,进行了手工拆分,今后再有的类似情况将不再另作备注。

On FAT drives, the directory that stores files in the Recycle Bin is called C:\RECYCLED, but on NTFS drives, its name is C:\RECYCLER. Why the name change?

在 FAT 格式的分区上,存储回收站文件的目录叫做 C:\RECYCLED,但在 NTFS 格式的分区上则叫 C:\RECYCLER。为什么会有这种变化呢?

The FAT and NTFS Recycle Bins have different internal structure because NTFS has this thing called “security” and FAT doesn’t. All recycled files on FAT drives are dumped into a single C:\RECYCLED directory, whereas recycled files on NTFS drives are separated based on the user’s SID into directories named C:\RECYCLER\S-…. (It has nothing to do with whether you are running English or Swedish Windows.)

FAT 分区和 NTFS 分区上的回收站的内部结构有所不同,因为 NTFS 文件系统有一种 FAT 文件系统所没有的功能,叫做『安全属性』。在 FAT 格式的分区上,所有删除的文件都被直接丢进了 C:\RECYCLED 目录里,而在 NTFS 分区上,回收站则按照用户的 SID 将删除的文件以 C:\RECYCLER\S-…. 的形式区别开来(这与你用的是英文版还是瑞典语版的 Windows 没有关系)。

Suppose the same directory name were used for both file systems, say, C:\RECYCLED. Since it is possible to upgrade a FAT drive to an NTFS drive with the CONVERT utility, this means that a FAT drive converted to NTFS would have a FAT-style Recycle Bin after the conversion. But since the names are the same, the Recycle Bin says, “Hey, look, here’s a C:\RECYCLED directory. That must be my NTFS Recycle Bin!” except that it isn’t. It’s a FAT Recycle Bin left over from the conversion. Giving the NTFS Recycle Bin a different name means that the Recycle Bin shell folder won’t get confused by the “wrong” type of recycle bin directory structure on an NTFS volume.

假设在两种格式的磁盘上,回收站文件夹的名字是相同的,都是 C:\RECYCLED。鉴于系统允许使用 CONVERT 工具将 FAT 格式的分区升级成为 NTFS 分区,这就意味着从 FAT 格式转换为 NTFS 格式的分区,在转换完成后就会有一个 FAT 格式的回收站(译注:上文所说的直接将文件丢进去,不按 SID 区隔的那种)。但由于(回收站的)名字是相同的,那么回收站功能便会认为,『嘿,看,这儿有个 C:\RECYCLED 目录,这肯定是我们 NTFS 格式的回收站没错!』,而事实上并非如此,它只是一个转换后遗留下来的 FAT 格式回收站而已。给 NTFS 格式回收站(目录)一个不同的名字,有助于令回收站功能不会在 NTFS 格式的卷上对『错误的』回收站目录结构产生疑惑。

Yes, the problem could have been solved some other way. For example, there could have been code to inspect the Recycle Bin directory to determine what format it is and ignore it if it didn’t match the actual file system. (Or, if you’re feeling really ambitious, somehow convert from one format to the other.) But that would be over-engineering. You have to write and test the detection (and possibly conversion) code, there’s the risk of a false-positive, the code runs at every boot, and it needs to be maintained whenever either the FAT or NTFS recycle bin format changes. All for a scenario that happens at most once per drive.

的确,这个问题也能通过其他方式解决。例如,回收站功能可以新增一段代码,来判断目录内的格式,并忽略与当前文件系统不相符的情况。(又或者真的很有雄心壮志的话,把不相符的格式转换为相符的也可以。)但是那样就成了过度开发的案例了。你得撰写相关的代码,对检测功能进行测试(可能还包括转换格式的功能),这其中存在判断错误的可能,这段代码会在每次系统启动时运行,并且每次 FAT 或 NTFS 文件系统的回收站格式发生变化时都要维护,而以上所有的麻烦,都只为了一个在每个磁盘上最多只会发生一次的事情。

Or you could change one text string and be done with it. (I could make some really awful “Gordian knot”/”string” remark here but will refrain.)

也可以选择就修改一个字符串(译注:RECYCLER 和 RECYELED 的区别)就搞定了。

TONT 32483 为什么有时损坏的二进制文件会令系统提示『程序太大,不能装入内存』?

原文链接:https://devblogs.microsoft.com/oldnewthing/20060130-00/?p=32483

译注:原文第一段比较长,为方便阅读,进行了手工拆分。

If you take a program and corrupt the header, or just take a large-ish file that isn’t a program at all and give it a “.exe” extension, then try to run it (Warning: Save your work first!), you will typically get the error “Program too big to fit in memory”. Why such a confusing error message? Why doesn’t it say “Corrupted program”?

随便找一个程序来,然后把它的文件头搞乱,或者干脆随便拿一个挺大的、不是应用程序的文件,并给它一个.exe的扩展名,然后尝试运行之(警告:先保存好你正在进行的工作!),通常你会得到一条错误信息:『程序太大,不能装入内存』。为什么是这么令人费解的一条错误信息呢?为什么不说是『程序已损坏』呢?

Because the program isn’t actually corrupted. Sort of.

因为从某种意义上讲,这个程序实际上并没有损坏。

A Win32 executable file begins with a so-called “MZ” header, followed by a so-called “PE” header. If the “PE” header cannot be found, then the loader attempts to load the program as a Win16 executable file, which consists of an “MZ” header followed by an “NE” header. If neither a “PE” nor an “NE” header can be found after the “MZ” header, then the loader attempts to load the program as an MS-DOS relocatable executable. If not even an “MZ” header can be found, then the loader attempt to load the program as an MS-DOS non-relocatable executable (aka “COM format” since this is the format of CP/M .COM files). In pictures:

一个 Win32 可执行文件的开头包含所谓的『MZ』文件头,紧跟着是所谓的『PE』头。如果找不到PE头,那么加载器就会尝试将程序按照 Win16 可执行文件进行读取,而 Win16 的文件头便是MZ后面跟一个NE。如果在MZ头之后既没有找到PE头,也没有找到NE头,那么加载器会尝试将程序按照MS-DOS可重定位可执行文件进行加载。如果连MZ头都没找到,那么加载器就会将其按照MS-DOS不可重定位可执行文件(也叫做COM格式,因为这是CP/M的.COM文件的格式)进行加载。总的来说就是:

MZ PE Win32
NE Win16
其它情况 MS-DOS 可重定位可执行文件
其它情况 MS-DOS 不可重定位可执行文件

Observe that no matter what path you take through the chart, you will always end up at something. There is no exit path that says “Corrupted program”. But where does “Program too big to fit in memory” come from?

很明显,根据上面表格中列出的情况,不管走哪条路最后都会到达某个终点,并且并没有哪个终点是显示『程序已损坏』这条消息的选项。话说回来,『程序太大,无法载入内存』又是怎么回事呢?

If the program header is corrupted, then various fields in the header such as those which specify the amount of memory required by the program will typically be nonsensical values. The loader sees an MS-DOS relocatable program that requires 800KB of conventional memory, and that’s where “Out of memory” comes from. An MS-DOS non-relocatable program contains no such information about memory requirements. The rule for loading non-relocatable programs is simply to load the program into a single 64KB chunk of memory and set it on its way. Therefore, a program with no “MZ” header but which is larger than 64KB in size won’t fit in the single 64KB chunk and consequently results in an “Out of memory” error.

如果某个程序的文件头损坏了,那么在文件头中的一些字段——例如指定程序所需内存数量的值通常会是一些毫无意义的数值。加载器会将其视为一个请求800KB常规内存的 MS-DOS 可重定位应用程序(译注:常规内存上限为640KB),而这就是『内存不足』消息的来源。MS-DOS 不可重定位应用程序是不包含类似所需内存数量之类的信息的,加载这类程序的路子,就是将其装入单独一段64KB内存并运行它。因此,一个没有MZ头、但是尺寸又比64KB大的程序自然无法装入64KB的内存段,由此引发了『内存不足』的错误。

And since people are certain to ask:

顺便一提吧,反正肯定会有人问:

“MZ” = the legendary Mark Zbikowski.

MZ:传奇人物 Mark Zbikowski 的缩写(译注:微软公司的元老级开发者)

“NE” = “New Executable”, back when Windows was “new”.

NE:新式可执行程序(New Executable)的缩写,那时候 Windows 还蛮『新』的。

“PE” = “Portable Executable”, because one of Windows NT’s claims to fame was its portability to architectures other than the x86.

PE:便携式可执行程序(Portable Executable)的缩写,因为 Windows NT 出名的原因之一就是其可以在 x86 平台之外的可移植性。

“LE” = “Linear Executable”, used by OS/2 and by Windows 95 device drivers.

LE:线性可执行程序(Linear Executable),由 OS/2 和 Windows 95 的驱动程序所使用。

TONT 32683 当网站依赖安全漏洞的时候

原文链接:https://devblogs.microsoft.com/oldnewthing/20060112-15/?p=32683

译注:原文第一段超级长,为方便阅读,进行了手工拆分。

Perhaps the biggest risk when making a change in the name of security is all the things that may have been relying on the previously-lax security settings. After all, disabling an insecure feature is easy. The hard part is disabling it while retaining compatibility with people who were relying on that feature.

可能以安全之名做出改变的最大风险,就是那些依赖从前并不那么严格的安全设置的东西。毕竟,关闭一项不安全的功能并不困难,困难的是在关闭它的同时,还能保持与依赖这些功能的人的兼容性。

In the security investigations I’ve been involved with, perhaps the largest chunk of my time is spent trying to find a way to mitigate the security hole without breaking existing customers. (And it’s the Line of Business scenario that is the biggest question mark.)

在我所参与过的安全审查工作中,可能花费时间最多的就是找到一条门路来减缓某个安全漏洞的影响,而不至于破坏既有客户的体验。(并且也是商业用户这条线上的问题最大)

Here’s a real-life example: Consider a sports web site which sells a service to subscribers wherein the site creates a pop-up window whenever a game’s score has changed or some other significant event has occurred. That way, you can leave your browser minimized and go about your day, but when something happens in the game, it will pop up an alert. The round of security changes in Windows XP SP2 broke this site because the rules on positioning of pop-up windows were tightened so that pop-up windows could not appear outside the browser itself. This prevents pop-up windows from being used to cover important browser elements (such as the status bar, the address bar, or a security dialog) and makes it harder for pop-ups to masquerade as system dialogs. But it also broke this company’s business model. And of course, if Microsoft does something that cause you to lose money, you sue. There were probably corporations that had internal web sites that relied on the ability to position pop-ups without restriction. Those corporations no doubt also complained about this change in the name of security.

来举一个现实的例子:假设有一个体育网站向客户销售一种服务,这种服务会在某场比赛的比分发生改变、或有重大事项发生时弹出一个窗口,如此你便可以将浏览器窗口最小化去做别的事,而当比赛出现变化时便会弹出提示。Windows XP SP2的一轮安全更新破坏了这一机制,因为弹出窗口的规则收紧了,现在弹出窗口不能在上级窗口范围之外弹出了。这一改变是用来放置窗口遮蔽浏览器的重要元素(如状态栏、地址栏,或某个安全对话框)的,也让弹出窗口冒充系统对话框的几率大减。然而这项措施也破坏了这家(体育网站)公司的商业模型。理所当然的是,如果微软公司的所作所为让你蒙受了经济损失,你当然会选择起诉。同样的,也有一些企业的内部网站依赖旧有的设计,来将弹出窗口不受限制地进行定位,这些企业也无一例外地抱怨这项以安全之名做出的改变。

As with most security changes that have compatibility consequences, a “safety valve” was added to return to the old insecure behavior for those customers who were relying on it. In this case, you can put the affected sites in the Trusted Sites zone and enable the “Allow script-initiated windows without size or position constraints” setting. But this is just a stop-gap, re-opening the security hole to let this site continue to operate the way it does. The real fix is not to rely on the security hole.

就像多数包含兼容性后遗症的安全更新一样,开发者增加了一道『安全阀』来方便那些仍然依赖旧有的、不安全的行为的客户。在这种情况下,你可以将受影响的网站放进『信任的站点』列表中,并启用『允许脚本启动的窗口不受大小或位置限制』的选项。不过,这只是一道权宜之计,等于将安全漏洞重新打开来,让那些网站可以继续按照旧有的方式运作。真正的修复方式,是不再依赖这些安全漏洞。

TONT 32693 『诱饵』视觉样式

原文链接:https://devblogs.microsoft.com/oldnewthing/20060111-09/?p=32693

During the development of Windows XP, the visual design team were very cloak-and-dagger about what the final visual look was going to be. They had done a lot of research and put a lot of work into their designs and wanted to make sure that they made a big splash at the E3 conference when Luna was unveiled. Nobody outside the visual styles team, not even me, knew what Luna was going to look like. On the other hand, the programmers who were setting up the infrastructure for visual styles needed to have something to test their code against. And something had to go out in the betas.

在 Windows XP 的开发过程中,视觉设计团队对系统最终的外观讳莫如深。团队进行了大量的研究,对设计投入了很大的精力,意在确保Luna主题在E3展会上揭晓时可以大放异彩。团队之外,没有任何人——即便是我对Luna会长什么样有所认知。另一方面,为视觉样式功能编写基础代码的工程师们,则需要一些可以用来测试他们代码的东西,而 Beta 版也总得放点什么进去。

The visual styles team came up with two styles. In secret, they worked on Luna. In public, they worked on a “decoy” visual style called “Mallard”. (For non-English speakers: A mallard is a type of duck commonly used as the model for decoys.) The ruse was so successful that people were busy copying the decoy and porting it to their own systems. (So much for copyright protection.)

视觉样式团队做了两个样式出来。在台面下,他们继续为Luna样式努力着,而面对公众时,他们做了一个『诱饵』视觉样式,名为『Mallard』(绿头鸭)。(致非英语用户:绿头鸭是一种常被用于诱饵模型的鸭子。)这一诡计实在是很成功,以至于人们都忙不迭地赶去复制这个诱饵主题、将其移植到他们的系统里去了。(版权保护什么的就算了吧。)

TONT 32703 『诱饵』控制面板

原文链接:https://devblogs.microsoft.com/oldnewthing/20060110-17/?p=32703

译注:原文第一段超级长,为方便阅读,进行了手工拆分。

Last time, we saw one example of a “decoy” used in the service of application compatibility with respect to the Printers Control Panel. Today we’ll look at another decoy, this time for the Display Control Panel.

在上一篇博文中,我们了解了一个与打印机控制面板相关的、用于服务应用程序兼容性的『诱饵』。今天我们来看另一个『诱饵』,这次是关于显示控制面板的。

When support for multiple monitors was being developed, a major obstacle was that a large number of display drivers hacked the Display Control Panel directly instead of using the documented extension mechanism. For example, instead of adding a separate page to the Display Control Panel’s property sheet for, say, virtual desktops, they would just hack into the “Settings” page and add their button there. Some drivers were so adventuresome as to do what seemed like a total rewrite of the “Settings” page. They would take all the controls, move them around, resize them, hide some, show others, add new buttons of their own, and generally speaking treat the page as a lump of clay waiting to be molded into their own image. (Here’s a handy rule of thumb: If your technique works only if the user speaks English, you probably should consider the possibility that what you’re doing is relying on an implementation detail rather than something that will be officially supported going forward.)

在开发多显示器支持的过程中,一个主要的障碍是有相当多的显卡驱动会对显示控制面板直接下手进行修改,而不是使用文档中载明的扩展机制。例如,这些驱动不采取向显示控制面板中增加一个单独的选项卡、来展示诸如虚拟桌面之类的功能的方式,而是直接对『设置』页面横加出手,把它们的按钮直接塞进去。有些驱动极富冒险精神,甚至把『设置』选项卡整个重写了一遍。这些驱动抄起选项卡里的控件来挪东挪西、变大变小、藏这显那,还加了些他们自己的按钮进去,总的来说就是将这个选项卡当成了一块粘土,想做成什么形状就做成什么形状。(这里有一条简明的经验法则:如果你的做法只对说英语的用户有效,那么你应该考虑一下你所做的事情正在依赖部署细节,而不是受官方支持、可以持续下去的东西。)

In order to support multiple monitors, the Settings page on the Display Control Panel underwent a major overhaul. But when you tried to open the Display Control Panel on a system that had one of these aggressive drivers installed, it would crash because the driver ran around rearranging things like it always did, even though the things it was manipulating weren’t what the developers of the driver intended!

为了实现对多显示器的支持,显示控制面板的『设置』页面做出了重大改动。然而,当你在某台安装了上述野心勃勃的显卡驱动的机器上打开显示控制面板的时候,程序会崩溃,因为驱动还在按照旧有的方式对控制面板里的控件大改一通,即便是如今它出手修改的东西已经与驱动的开发者所想的已经完全不同了!

The solution was to create a “decoy” Settings page that looked exactly like the classic Windows 95 Settings page. The decoy page’s purpose in life was to act as bait for these aggressive display drivers and allow itself to be abused mercilessly, letting the driver have its way. Meanwhile, the real Settings page (which is the one that was shown to the user), by virtue of having been overlooked, remained safe and unharmed.

解决方案,则是创建一个『诱饵』设置页面,这个页面看上去与旧式的 Windows 95(显示控制面板的)设置页面完全一样,而它的一切目的就是为了诱使那个野心勃勃的显卡驱动对它毫无怜悯之心地一通乱改,让驱动能心满意足。而与此同时,真正的『设置』页面(展示给用户的),由于被(驱动)忽视掉了,得以岁月静好。

There was no attempt to make this decoy Settings page do anything interesting at all. Its sole job was to soak up mistreatment without complaining. As a result, those drivers lost whatever nifty features their shenanigans were trying to accomplish, but at least the Display Control Panel stayed alive and allowed the user to do what they were trying to do in the first place: Adjust their display settings.

这个『诱饵』设置页面并没有任何有趣的目的,其全部职责就是毫无怨言地迎击驱动的乱搞。最后,这些驱动要展示的那些花哨的功能一个也没能显示出来,但至少显示控制面板安然度过了这一切,使得用户能做他们一开始便想要做的事情:调整显示设置。

TONT 32723 当应用程序认为系统永远都不会变的时候:第3章

原文链接:https://devblogs.microsoft.com/oldnewthing/20060109-27/?p=32723

(译注:第2章在原Blog中不存在,原因未知)

One of the stranger application compatibility puzzles was solved by a colleague of mine who was trying to figure out why a particular program couldn’t open the Printers Control Panel. Upon closer investigation, the reason became clear. The program launched the Control Panel, used FindWindow to locate the window, then accessed that window’s “File” menu and extracted the strings from that menu looking for an item that contained the word “Printer”. It then posted a WM_COMMAND message to the Control Panel window with the menu identifier it found, thereby simulating the user clicking on the “Printers” menu option.

我的一位同事曾解决过的一桩诡异的应用程序兼容性问题,是找出为什么某个程序无法打开打印机控制面板的原因。在深入调查后,原因变得明朗起来。这个程序会打开控制面板,用 FindWindow 找到控制面板的窗口,然后去访问这个窗口的 File(文件)菜单,把这个菜单里的菜单项字符串解析出来,然后在其中找到带有 Printer(打印机)这个词的项目,然后向控制面板窗口发送 WM_COMMAND 窗体消息,以刚才找到的菜单项为参数。经过以上一通操作,便完成了模拟用户单击『打印机』菜单项这个操作。(译注:可自行参考 Windows 3.x 的控制面板长什么样子,以便更好理解上文描述的操作)

With Windows 95’s Control Panel, this method fell apart pretty badly. There is no “Printers” option on the Control Panel’s File menu. It never occurred to the authors of the program that this was a possibility. (Mind you, it was a possibility even in Windows 3.1: If you were running a non-English version of Windows, the name of the Printers option will be something like “Skrivare” or “Drucker”. Not that it mattered, because the “File” menu will be called something like “Arkiv” or “Datei”! The developers of this program simply assumed that everyone in the world speaks English.)

到了 Windows 95 的控制面板里,这种操作可谓一败涂地。控制面板的『文件』菜单里并没有『打印机』这一项,对软件的编写者来说,这是根本不可能发生的事情。(需要提醒的是,即便在 Windows 3.1 中,这也是一件有可能发生的事:如果你运行的 Windows 不是英语版本,那么『打印机』一项的名字可能叫做 Skrivare(译注:瑞典语的『打印机』)或者 Drucker(译注:德语的『打印机』),但这其实也不是最大的问题,因为与此同时『文件』菜单的名字可是会叫做 Arkiv 或者 Datei(译注:分别为瑞典语和德语的『文件』)呢!编写这个软件的开发者估计简单的认为这个世界上的所有人都是讲英语的吧。)(译注:也可能人家根本就没想在英语区之外发行?)

The code never checked for errors; it plowed ahead on the assumption that everything was going according to plan. The code eventually completed its rounds and sent a garbage WM_COMMAND message to the Control Panel window, which was of course ignored since it didn’t match any of the valid commands on that window’s menu.

程序的代码从来都没有对错误进行过检查,只是一味地勇往直前,假定一切都会按计划进行而已。代码做完了它的工作,向控制面板窗口发送了一个无效的 WM_COMMAND 窗体消息,而这个消息由于没有包含针对窗体菜单的任何有效指令,理所当然地被系统忽略了。

The punch line is that the mechanism for opening the Printers Control Panel was rather clearly spelled out on the very first page of the “Control Panel” chapter of the Windows 3.1 SDK:

笑点在于,打开打印机控制面板的方式,实际上在 Windows 3.1 SDK『控制面板』章节的第一页就清清楚楚地写着:

The following example shows how an application can start Control Panel and the Printers application from the command line by using the WinExec function:

以下案例说明如何使应用程序通过调用 WinExec 函数来打开控制面板以及打印机设置界面:

WinExec(“control.exe printers”, SW_SHOWNORMAL);

In other words, they didn’t even read past the first page.

换句话说,这个软件的开发者连第一页都没读过去。

The solution: Create a “decoy” Control Panel window with the same class name as Windows 3.1, so that this program would find it. The purpose of these “decoys” is to draw the attention of the offending program, taking the brunt of the mistreatment and doing what they can to mimic the original behavior enough to keep that program happy. In this case, it waited patiently for the garbage WM_COMMAND message to arrive and dutifully launched the Printers Control Panel.

至于解决方案,则是创建了一个用作『诱饵』的控制面板窗口,这个窗口的类名与 Windows 3.1 的控制面板窗口一致,以便让这个程序能找到它。这个诱饵的作用是吸引这个无礼的应用程序的注意力,首当其冲地模仿旧式控制面板的行为,来让这类应用程序心满意足。在这个案例中,它的作用是耐心等待那个无效的 WM_COMMAND 窗体消息的来临,然后尽职尽责地打开『打印机』控制面板。

Nowadays, this sort of problem would probably have been solved with the use of a shim. But this was back in Windows 95, where application compatibility technology was still comparatively immature. All that was available at the time were application compatibility flags and hot-patching of binaries, wherein the values are modified as they are loaded into memory. Using hot-patching technology was reserved for only the most extreme compatibility cases, because getting permission from the vendor to patch their program was a comparatively lengthy legal process. Patching was considered a “last resort” compatibility mechanism not only for the legal machinery necessary to permit it, but also because patching a program fixes only the versions of the program the patch was developed to address. If the vendor shipped ten versions of a program, ten different patches would have to be developed. And if the vendor shipped another version after Windows 95 was delivered to duplication, that version would be broken when Windows 95 hit the shelves.

现如今,这类问题一般会通过使用『楔子』一类的方式解决,但这个案例是在 Windows 95 的年代发生的,那时应用程序兼容性技术相对来说还不够成熟,而那时能用的办法就是应用程序兼容性标签,以及对二进制文件应用热修复补丁,在其加载入内存时对二进制数据进行修改。热修复补丁这一招只会被留待遇到最棘手的兼容性问题时才会使用,因为从软件发行商哪里获得对其程序进行修改的许可,是一个冗长的法律过程。打补丁被视为是实现兼容性问题解决的『最终手段』,不仅仅因为获得许可要经过机械繁复的法律流程,同时也是因为这样只能修复兼容性补丁所针对的该软件特定版本的问题。如果软件发行商发布了10个版本的应用程序,那就要开发10个不同的补丁。而如果软件发行商在 Windows 95 送厂之后又发布了新版本,那么这个新版本在 Windows 95 上架销售之后便仍存在兼容性问题。

It is important to understand the distinction between what is a documented and supported feature and what is an implementation detail. Documented and supported features are contracts between Windows and your program. Windows will uphold its end of the contract for as long as that feature exists. Implementation details, on the other hand, are ephemeral; they can change at any time, be it at the next major operating system release, at the next service pack, even with the next security hotfix. If your program relies on implementation details, you’re contributing to the compatibility cruft that Windows carries around from release to release.

理解文档中受支持的功能和部署细节的区别很重要。文档中受支持的功能是 Windows 和你的程序之间的契约,Windows 在这个功能的存续期间会信守承诺。而另一方面,部署细节则是稍纵即逝的,可能随时发生变化,变化可能发生在下一个系统大版本,下一个 Service Pack,甚至是下一个安全更新补丁。如果你的程序依赖部署细节,那你不过是在为 Windows 代代相传的、沉重的兼容性包袱添砖加瓦罢了。

Over the next few days, I’ll talk about other decoys that have been used in Windows.

接下来的几天里,我会讲一讲 Windows 中其它的一些兼容性『诱饵』。

TONT 33023 关于无法再支持已经无人再制造的硬件这件事

原文链接:https://devblogs.microsoft.com/oldnewthing/20051209-12/?p=33023

Windows Vista will not have support for really old DVD drives. (The information below was kindly provided to me by the optical storage driver team.)

Windows Vista 对于一些特别老型号的 DVD 光驱已经不再提供支持了。(以下信息由光存储驱动开发组友情提供。)

When PC DVD drives first came out in 1998, the drives themselves did not have support for region codes but instead relied on (and in fact the DVD specification required) the operating system to enforce region coding, with the further understanding that starting on January 1, 2000 all newly-manufactured drives would support region coding in hardware rather than relying on software enforcement. For the purpose of this discussion, I will call the two types of drives “old” (manufactured before 2000) and “new” (manufactured on or after January 1, 2000).

1998年,PC 上的 DVD 光驱刚刚出现的时候,光驱硬件自身并不支持区码限制,而是依赖操作系统来确保这个限制(实际上也是 DVD 标准所要求的),不过在后来更新的标准中,自2000年1月1日起,所有新生产的DVD光驱都应当在硬件、而不是在软件中确保区码限制。为了讨论方便,接下来我将这两种光驱称作『旧』光驱(2000年以前生产)和『新』光驱(2000年1月1日起生产)。

It is that software enforcement that is going away. Turns out that the enforcement of region coding in software had its own problems:

在这个转变的过程中,由软件实现的区码限制消失了,原来是因为由软件实现的区码限制有它自己的问题:

  • It was impossible for third-parties to compile their own CDROM.SYS from the source code in the DDK because the region code enforcement code was not included in the DDK.
    第三方开发者无法从DDK(驱动程序开发包)的源代码中编译他们自己的 CDROM.SYS,因为 DDK 中没有区码限制相关的代码。
  • The region code enforcement code would sometimes mistake a new drive for an old one, resulting in customers unable to play DVDs. Even worse, the driver test team could not reproduce the problem reliably, and the problem went away entirely once a debugger was attached to the system.
    区码限制功能有时候会将新光驱当作旧光驱,导致客户无法播放DVD。更糟糕的是,驱动测试组无法可靠地复现这个问题,而且一接入调试器这个问题就消失了。
  • The code to support the older drives is complex, and the drives that the optical storage team purchased prior to January 1, 2000 are dead or dying. Consequently, testing the code that provides support for old drives has become increasingly difficult, and when the last old drive finally gives up the ghost, testing will become impossible altogether.
    支持旧光驱区码限制的代码很复杂,并且在光存储团队在2000年1月日以前购置的(测试用)光驱大多已经或差不多坏掉了。由此,测试支持旧光驱代码的工作变得愈加困难,等到最后一台旧光驱坏掉的时候,测试工作就会变得完全无法进行了。

These were among the considerations which contributed to the decision to stop supporting these old drives.

以上这些都在决定停止支持这些旧光驱的考虑之中。

What does this mean for you? Almost certainly, the answer is “absolutely nothing”.

而这对你又意味着什么呢?基本可以肯定,答案是『毫无意义』。

First, there is no change to the way data is read from DVD drives, so data discs will still work the same way as they do today. Second, all new DVD drives will continue to run as they did before; the only change is that the risk of mis-identification as an old drive has been removed. Only if you have an old drive will you notice anything different, namely that encrypted/regionalized DVD movies will no longer play. And since the average drive lifetime is only three years, the number of such old drives that are still working is vanishingly small. Not even the optical drive test team can manage to keep their old drives alive that long.

首先,从DVD光驱中读取数据的流程没有任何改变,故而数据光盘的读取效果与现今别无二致。其次,所有的新DVD光驱都会像过去那样正常工作,唯一的变化是会造成将新光驱当作旧光驱这个失误的相关代码已经被移除了。只有当你手里的光驱是『旧』光驱的时候,你才会发现有不一样的情况发生,亦即加密的或有区码限制的DVD影碟无法播放。鉴于光驱的使用寿命平均只有三年,会有这个问题的旧光驱的数量正在急剧缩小。(别忘了,)就连光驱测试组的成员们都没法让这些旧光驱活那么久。

TONT 33043 用实体物品作为提醒

原文链接:https://devblogs.microsoft.com/oldnewthing/20051208-10/?p=33043

On our team, we have a mailing list where people can report problems. Those people could be testers from our team or they could be people from elsewhere in the company. Everybody on the team is expected to keep an eye on the messages and debug problems in their area. The job of monitoring the mailing list to ensure that every issue is ultimately addressed rotates according to a predetermined schedule, and in addition to receiving a piece of reminder mail at 4pm the business day before it’s your turn, you will also find a Mickey Mouse ears hat on your desk when you arrive in the morning.

在我们的团队中,有一个邮件列表用来报告问题,报告问题的人既可能是团队中的测试人员,也可能是公司里其他部门的人。团队成员们都有责任盯好消息,并处理自己所负责的调试工作。监视邮件列表、以便将每个问题都能最重转达给响应人员的工作是按照一个预定的计划轮转的,并且除了工作日下午4点会收到一封邮件、提醒第二天轮到你来做这项工作之外,第二天你的桌子上还会多出一顶米奇老鼠的帽子。

I bought this hat in Disneyland a few years ago and somehow managed to convince the person operating the sewing machine to stitch the name “Dev O’Day” on the back. “It’s an Irish name,” I explained, but it also stands for “Developer of the Day”, which is the title we use for the person who monitors the mailing list.

这顶帽子是几年前我去迪士尼乐园的时候买的,并且设法说服了操作缝纫机给帽子织上名字的人,让他在帽子背面织了『Dev O’Day』这个名字。『这是个爱尔兰名字』,我是这么跟他解释的,不过这个缩写也代表『今日开发者』,亦即我们给今天盯着邮件列表的人的头衔。

One of our team members went on vacation to Disneyland the following year and brought back a back-up hat, which sits in my office. The back-up hat is occasionally brought into service when the primary Dev O’Day hat goes missing, at which point a Search and Rescue mission is undertaken to locate the hat and restore it to circulation. (It’s usually just sitting in the office of someone who was Developer of the Day recently and merely forgot to hand the hat off at the end of the day.)

我们团队里的一位成员第二年的时候也去了迪士尼乐园独家,并且买回来一定备用的帽子,这顶帽子放在我的办公室里。备份帽偶尔会在『主』帽消失的时候用来顶替它的工作,而这时『搜救行动』也会开展起来,将『主』帽重回流通之中。(通常来说,『主』帽只是被留在了最近成为『今日开发者』的某个成员的办公室里,忘了在当天结束的时候交出去而已。)