TONT 34513 Windows 95 的安装程序用了多少张软盘才装下?

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

Thirteen.

13张。

In case you were wondering.

如果你真那么想知道的话。

And those were thirteen of those special Distribution Media Format floppies, which are specially formatted to hold more data than a normal 1.44MB floppy disc. The high-capacity floppies reduced the floppy count by two, which resulted in a tremendous savings in cost of manufacturing and shipping.

并且这13张软盘都是所谓的『分发媒体格式』(Distribution Media Format)的软盘,经过特殊的格式化,可以存储比普通的1.44MB软盘更多的数据。这些高容量软盘让(一套Windows 95安装程序)所需的软盘数量减少了2张,从而在制造和运输的过程中减少了海量的成本。

(I’m sure there are the conspiracy-minded folks who think that DMF was invented as an anti-piracy measure. It wasn’t; it was a way to reduce the number of floppy disks. That the disks were difficult to copy was a side-effect, not a design goal.)

(我觉得肯定有些阴谋论者认为DMF软盘是某种反盗版措施,然而实际上并非如此,它只是一种减少软盘数量的方式而已。这些磁盘难以复制只是副作用,而不是设计目的。)

(For comparison, Windows 3.1 came on six floppies. Windows NT 3.1 came on twenty-two. And yesterday, one of my colleagues reminded me that Windows NT setup asked for the floppy disks out of order! I guess it never occurred to them that they could renumber the disks.)

(作为对比,Windows 3.1 用了6张软盘,Windows NT 3.1 用了22张。并且昨天,有个同事还告诉我 Windows NT 安装程序要求用户提供软盘的时候是不按顺序的!我觉得这个问题他们应该从来没有遇到过,因为他们可以给磁盘重新标号。)

TONT 34563 当人们要将安全漏洞作为功能的时候:静默安装未经认证的驱动

原文链接:https://devblogs.microsoft.com/oldnewthing/20050816-08/?p=34563

Probably the single greatest source of bluescreen crashes in Windows XP is buggy device drivers. Since drivers run in kernel mode, there is no higher authority checking what they’re doing. If some user-mode code runs amok and corrupts memory, it’s just corrupting its own memory. The process eventually crashes, but the system stays up. On the other hand, if a driver runs amok and corrupts memory, it’s corrupting your system and eventually your machine dies.

Windows XP 蓝屏崩溃的最大原因之一是有问题的设备驱动。由于驱动运行在内核模式下,已经没有更高级别的机制来监控它们在做什么了。如果一段用户模式下的代码发飙,破坏了内存数据,那它也只是破坏了它自己的内存段而已。其进程最终会崩溃,但整个系统还是好好的。另一方面,如果某个驱动程序发飙,破坏了内存数据,那它破坏的是整个系统,最终你的机器会停止运转。

In acknowledgement of the importance of having high-quality drivers, Windows XP warns you when an uncertified driver is being installed. Which leads to today’s topic, a question from a device driver author.

鉴于驱动高质量的重要性,Windows XP 会在安装未经认证的驱动时警告用户,这就引出了今天的话题,是一位来自某个设备驱动程序作者的提问:

When I try to install any driver, I get a User Consent Dialog box which tells the user that this is an unsigned driver. Is it possible to author a driver installation package that by-passes this user consent dialog box?

当我尝试安装驱动时,系统都会弹出一个请求用户允许的对话框,告诉用户正在安装一个未签名的驱动。有没有办法编写一种驱动安装包,能让系统不显示这个对话框?

The whole purpose of that dialog is to prevent the situation you desire from happening! [typo fixed 5pm] If you don’t want the warning dialog, submit your driver for certification. (For testing purposes, you can sign your drivers with the test root certificate and install the test root certificate before running your setup program. Of course, installing the test root certificate also causes the desktop to read “For test purposes only” as a reminder that your machine is now allowing test-signed drivers to be installed.)

这个对话框的存在意义,可正是阻止你所想要的这种事情的发生啊!如果你不想让这个对话框出现,那就把你的驱动提交认证就好。(如果是出于测试的目的,你可以将你的驱动用测试根证书签名,并且在运行你的安装程序之前安装这个测试根证书。当然,安装测试根证书会让桌面上冒出“仅供测试使用”的字样,用来提醒你你的机器目前允许安装测试签名的驱动。)

Driver writers, of course, find the certification process cumbersome and will do whatever they can to avoid it. Because, of course, if you submit your driver for certification, it might fail! This has led to varying degrees of shenanigans to trick the WHQL team into certifying a driver different from the one you intend to use. My favorite stunt was related to my by a colleague who was installing a video card driver whose setup program displayed a dialog that read, roughly, “After clicking OK, do not touch your keyboard or mouse while we prepare your system.” After you click OK, the setup program proceeds to move the mouse programmatically all over the screen, opening the Display control panel, clicking on the Advanced button, clicking through various other configuration dialogs, a flurry of activity for what seems like a half a minute. When faced with a setup program that does this, your natural reaction is to scream, “Aaaiiiiigh!”

而驱动的编写者们,自然而然地发现这个认证过程缓慢而冗长,继而想出各种各样的办法来避免之。毕竟,如果你把自己的驱动提交认证的话,还是有通不过的可能性的!这种可能性让开发者们想出了各种稀奇古怪的门路,让WHQL团队给你所提交的驱动进行认证,但实际发布的则不是那一个。我所最喜欢的一则是由我的同事提供的,当他安装某款显卡驱动的时候,安装程序弹出一个对话框,上面大体上写着这些内容:“点击OK后,在我们帮你为系统进行准备配置时,请不要操作键盘或鼠标。”点击OK之后,安装程序就开始以程序操作你的鼠标满屏幕跑,打开『显示』控制面板,点击『高级』按钮,然后这里那里点击很多配置项,一同忙乱下来大概要花半分钟左右。面对这样的安装程序,你的内心想必是在大喊『啊啊啊啊啊』的吧。

TONT 34623 为什么 Windows 的错误报告程序昵称叫『Dr. Watson』?

原文链接:https://devblogs.microsoft.com/oldnewthing/20050810-13/?p=34623

The nickname for the feature known as Windows Error Reporting is “Dr. Watson”. Where did that name come from?

Windows 的错误报告功能有个昵称叫『Dr. Watson』(华生博士),这个名字是从哪来的呢?

As you have probably guessed, The name Dr. Watson was inspired by the character of Dr. Watson, the assistant to Sherlock Holmes in the stories by Arthur Conan Doyle.

如你所想,『华生博士』这个名字是受亚瑟·柯南道尔笔下的夏洛克·福尔摩斯的助手华生博士启发而起的。

It is my understanding that the doctor was originally developed as part of Windows 3.0 beta testing. His job was to record data about application crashes to a file, so that the file could be uploaded and included with bug reports. The icon was (and continues to be) a friendly doctor using his stethoscope to investigate a problem.

据我所了解,Dr. Watson 原本是作为 Windows 3.0 的 beta 测试工具被开发出来的,其工作是将崩溃的应用程序的数据记录到文件,以便将其嵌入到bug报告中进行上传。Dr. Watson 的图标曾经(并且至今如此)是一位用听诊器在调查问题的、和善的博士。

The Doctor has remained true to the “capture information about an error” aspect of his job. In the meantime, the word “Watson” has expanded its meaning to encompass anonymous end-user feedback mechanisms in general, such as “Content Watson”. (But if you hear “Watson” by itself, the speaker is almost certainly talking about error reporting.)

Dr. Watson 的工作『获取关于错误的信息』方面的描述一直保持不变。与此同时,Watson 这个词的含义也被扩展,囊括了面向最终用户的匿名反馈事项,例如『Content Watson』这种用法。(不过如果你单独听到 Watson 这个词,那说话者多半肯定是在讨论错误报告这回事。)

TONT 34783 你所说的那个叫『网站』的东西是什么?

原文链接:https://devblogs.microsoft.com/oldnewthing/20050728-16/?p=34783

One reaction I’ve seen when people learn about all the compatibility work done in the Windows 95 kernel is to say,

当人们对 Windows 95 内核所作出的兼容性努力发表意见时,我所知的其中一条是:

Why not add code to the installer wizard [alas, page is now 404] which checks to see if you’re installing SimCity and, if so, informs you of a known design flaw, then asks you to visit Electronic Arts’ webpage for a patch?

为什么不在安装程序里加一行代码(可惜这个页面已经404了)(译注:所以这里就不再引用失效链接了),让它可以检测到你是不是正在安装《模拟城市》,如果是的话,就提醒你游戏里的bug,然后帮你打开EA的网站去下载补丁呢?

Let’s ignore the issue of the “installer wizard”; most people do not go through the Add and Remove Programs control panel to install programs, so any changes to that control panel wouldn’t have helped anyway.

这里我们先忽略『安装程序』这个说法,毕竟大多数人是不会跑到控制面板的『添加/删除程序』里去安装新应用的,所以对控制面板做出变动并没有什么帮助。

But what about detecting that you’re running SimCity and telling you to get a patch from Electronic Arts’ web site?

姑且说,系统能不能做到检测你开启了《模拟城市》,然后通知你去EA的网站上下载补丁呢?

Remember, this was 1993. Almost nobody had web sites. The big thing was the “Information Superhighway”. (Remember that? I don’t think it ever got built; the Internet sort of stole its thunder.) If you told somebody, “Go to Electronic Arts’ web site and download a patch”, you’d get a blank stare. What’s a “web site”? How do I access that from Prodigy? I don’t have a modem. Can you mail me their web site?

请记住,那是1993年,基本上没什么人开设了『网站』这种东西,那时候的热门话题叫『信息高速公路』。(还记得这个词吗?我反正没记得这东西建成了没有,『互联网』把它的风头全抢尽了。)如果那年头你跟别人说『去EA的网站上下个补丁』,得到的只能是一脸茫然:『网站』是嘛玩意?我怎么访问它?我家又没有调制解调器,你能把他们的网站寄给我吗?

In Windows XP, when Windows detects that you’re running a program with which it is fundamentally incompatible, you do get a pop-up window directing you to the company’s web site. But that’s because it’s now 2005 and even hermits living in caves have email addresses.

在 Windows XP 中,当 Windows 检测到你运行的程序存在完全不兼容的情况时,你的确会得到一项提示,将你导向开发这个软件的公司的网站。但这是因为这时已经是2005年了,就连住在山洞里的隐士都有电子邮件地址了。

In 1993, things were a little different.

而1993年的时候,事情可不太一样。

(Heck, even by 1995 things most people did not have Internet access and those few that did used modems. Requiring users to obtain Internet access in order to set the computer clock via NTP would have been rather presumptuous.)

(1995年的时候,大多数人都没法上网,而仅有的能上网的人倒的确都在用调制解调器。让用户上网就为了能通过NTP服务设置一下本机的时钟就更加扯淡了。)

TONT 34883 为什么 FindFirstFile 会同时查找短文件名?

原文链接:https://devblogs.microsoft.com/oldnewthing/20050720-16/?p=34883

The FindFirstFile function matches both the short and long names. This can produce somewhat surprising results. For example, if you ask for “*.htm”, this also gives you the file “x.html” since its short name is “X~1.HTM”.

FindFirstFile 函数会同时匹配短文件名和长文件名,有时这种设计会带来一些意料之外的结果。例如,如果你查找『*.htm』,x.html(译注:注意此处的扩展名是HTML,其在8.3形式下为HTM,感谢石樱灯笼在评论中指出)也会出现在结果中,因为它的短文件名是X~1.HTM。

Why does it bother matching short names? Shouldn’t it match only long names? After all, only old 16-bit programs use short names.

为什么要去匹配短文件名呢,只匹配长文件名不就够了吗?毕竟只有旧式的16位应用程序会用短文件名了。

But that’s the problem: 16-bit programs use short names.

然而这却正视问题所在:16位应用程序使用的是短文件名。

Through a process known as generic thunks, a 16-bit program can load a 32-bit DLL and call into it. Windows 95 and the Windows 16-bit emulation layer in Windows NT rely heavily on generic thunks so that they don’t have to write two versions of everything. Instead, the 16-bit version just thunks up to the 32-bit version.

通过名为通用 Thunk 的过程,16位应用程序可以加载32位的DLL并调用之。Windows 95 和 Windows NT 中的 16 位 Windows 模拟层对于通用 Thunk 重度依赖,这样才不必为各种各样的东西编写2个版本,而是让 16 位的调用直接与 32 位的相关调用进行联动。

Note, however, that this would mean that 32-bit DLLs would see two different views of the file system, depending on whether they are hosted from a 16-bit process or a 32-bit process.

然而需要注意的是,如此一来32位的DLL便对文件系统有了两种观察方式,具体取决于其宿主进程是16位还是32位。

“Then make the FindFirstFile function check to see who its caller is and change its behavior accordingly,” doesn’t fly because you can’t trust the return address.

『那就让 FindFirstFile 看看调用方是谁,然后执行不同的行为不就好了』,这种想法是不现实的,因为你无法信任返回地址。

Even if this problem were solved, you would still have the problem of 16/32 interop across the process boundary.

就算能解决这个问题,你还是要面对16/32位进程边界间互操作的问题。

For example, suppose a 16-bit program calls WinExec(“notepad X~1.HTM”). The 32-bit Notepad program had better open the file X~1.HTM even though it’s a short name. What’s more, a common way to get properties of a file such as its last access time is to call FindFirstFile with the file name, since the WIN32_FIND_DATA structure returns that information as part of the find data. (Note: GetFileAttributesEx is a better choice, but that function is comparatively new.) If the FindFirstFile function did not work for short file names, then the above trick would fail for short names passed across the 16/32 boundary.

例如,假设某个程序调用了WinExec(“notepad X~1.HTM”),那么32位的记事本最好是去打开X~1.HTM,即便这是个短文件名。此外,获取文件属性(例如文件的最后访问时间)的一种通常方式便是调用 FindFirstFile 并提供文件名,因为 WIN32_FIND_DATA 结构会将这类信息包含在返回中。(请注意:使用 GetFileAttributesEx 是更好的做法,不过这个函数相对来说还比较新就是了。)如果 FindFirstFile(在32位程序调用它的时候)不能使用短文件名,那么前述的做法就会失效,因为此时短文件名跨越了16/32位的边界。

As another example, suppose the DLL saves the file name in a location external to the process, say a configuration file, the registry, or a shared memory block. If a 16-bit program program calls into this DLL, it would pass short names, whereas if a 32-bit program calls into the DLL, it would pass long names. If the file system functions returned only long names for 32-bit programs, then the copy of the DLL running in a 32-bit program would not be able to read the data written by the DLL running in a 16-bit program.

另一个例子是,假设某个DLL将文件名保存在进程之外的某处,例如配置文件中、注册表中,或某个共享的内存区域里。如果16位应用程序调用了这个DLL,那么它传入的就是短文件名,而32位应用程序调用时则会传入长文件名。如果文件系统函数只为32位应用程序返回长文件名,那么运行在32位应用程序下的这个DLL就无法读取由16位应用程序调用其时写入的数据了。

TONT 34893 ES_OEMCONVERT 是做什么用的?

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

The ES_OEMCONVERT edit control style is a holdover from 16-bit Windows. This ancient MSDN article from the Windows 3.1 SDK describes the flag thus:

编辑控件的 ES_OEMCONVERT 样式是从 16 位 Windows 中继承下来的。下面这篇在 Windows 3.1 SDK 中古老的 MSDN 文章对这个标志是这样描述的:

ES_OEMCONVERT causes text entered into the edit control to be converted from ANSI to OEM and then back to ANSI. This ensures proper character conversion when the application calls the AnsiToOem function to convert a Windows string in the edit control to OEM characters. ES_OEMCONVERT is most useful for edit controls that contain filenames.

ES_OEMCONVERT 标记会将输入到编辑控件的文字从 ANSI 编码转换到 OEM 编码,然后再转回 ANSI 编码。通过这样操作,可以保证应用程序调用AnsiToOem 将编辑控件中的字符转换为 OEM 编码的字符时,可以获得恰当的结果。ES_OEMCONVERT  在包含文件名的编辑控件中最有裨益。

Set the wayback machine to, well, January 31, 1992, the date of the article.

让我们把时间倒回1992年1月31日,也就是上面那段文字那时候。

At this time, the predominant Windows platform was Windows 3.0. Windows 3.1 was still a few months away from release, and Windows NT 3.1 was over a year away. The predominant file system was 16-bit FAT, and the relevant feature of FAT of this era for the purpose of this discussion is that file names were stored on disk in the OEM character set. (We discussed the history behind the schism between the OEM and ANSI code pages in an earlier article.)

那个时候,占据主导地位的 Windows 平台是 Windows 3.0。Windows 3.1 还得再过几个月才会发布,而 Windows NT 3.1 还得再等一年。那时占主导地位的文件系统是 16 位 FAT,而与此处讨论相关的 FAT 文件系统的设计,则是磁盘上存储的文件名使用的是 OEM 字符集。(我们在早先的一篇文章中讨论过有关 OEM 和 ANSI 代码页之间的分崩离析。)(译注:链接已失效,无法查证)

Since GUI programs used the ANSI character set, but file names were stored in the OEM character set, the only characters that could be used in file names from GUI programs were those that exist in both character sets. If a character existed in the ANSI character set but not the OEM character set, then there would be no way of using it as a file name; and if a character existed in the OEM character set but not the ANSI character set, the GUI program couldn’t manipulate it.

由于 GUI 程序用的是 ANSI 字符集,而文件名是用 OEM 字符集存储的,所以在 GUI 应用程序中使用的文件名,其字符集只能是在两种字符集中共存的那些。如果某个字符在 ANSI 字符集中存在,但并不存在于 OEM 字符集中,那么就不能讲这个字符用在文件名中;反之,如果某个字符在 OEM 字符集中存在,但在 ANSI 字符集中不存在,那么 GUI 应用程序也搞不定它。

The ES_OEMCONVERT flag on a edit control ensures that only characters that exist in both the ANSI and OEM character sets are used, hence the remark “ES_OEMCONVERT is most useful for edit controls that contain filenames”.

编辑控件中的 ES_OEMCONVERT 样式可以保证只有在 ANSI 和 OEM 两种字符集中共存的字符才能使用,也就印证了『ES_OEMCONVERT  在包含文件名的编辑控件中最有裨益』的说法。

Fast-forward to today.

回到现在。

All the popular Windows file systems support Unicode file names and have for ten years. There is no longer a data loss converting from the ANSI character set to the character set used by the file system. Therefore, there is no need to filter out any characters to forestall the user typing a character that will be lost during the conversion to a file name. In other words, the ES_OEMCONVERT flag is pointless today. It’s a leftover from the days before Unicode.

如今所有流行的 Windows 文件系统都支持 Unicode 文件名,并且已经如此十年了(译注:原文发布时间为2005年7月19日,Windows 3.0 发布时间为1990年5月22日),在将(文件名中的字符从)ANSI 字符集转换为文件系统使用的字符集(Unicode)不会再有数据丢失的问题了。因此也没有必要再预先将用户录入文件名时,可能在后期转换中丢失的字符过滤掉了。换句话说,ES_OEMCONVERT 这个样式标记已经毫无意义了,只是一个在 Unicode 年代之前的遗留而已。

Indeed, if you use this flag, you make your program worse, not better, because it unnecessarily restricts the set of characters that the user will be allowed to use in file names. A user running the US-English version of Windows would not be allowed to enter Chinese characters as a file name, for example, even though the file system is perfectly capable of creating files whose names contain those characters.

实际上,如果你非要用这个样式标记不可,只会让你的程序更糟糕而不是更优秀,因为对用户在文件名中允许使用过的字符集进行限制已经毫无必要。例如,(在你经过这样设计的应用程序中,)使用美国英语版本 Windows 的用户就不能输入中文字符作为文件名了,即便是文件系统可以完美支持创建包含那些(中文)字符的文件名也一样。

TONT 34913 如果 InitCommonControls 什么也没做,为什么还得调用它?

原文链接:https://devblogs.microsoft.com/oldnewthing/20050718-16/?p=34913

One of the problems beginners run into when they start using shell common controls is that they forget to call the InitCommonControls function. But if you were to disassemble the InitCommonControls function itself, you’ll see that it, like the FlushInstructionCache function, doesn’t actually do anything.

初学者学习使用系统外壳通用控件时,经常遇到的其中一个问题是忘记调用 InitCommonControls  方法。不过,如果对 InitCommonControls 方法反编译一下的话,你会发现它像 FlushInstructionCache 一样,事实上什么事情也没做。

Then why do you need to call it?

那么,必须调用它的意义何在呢?

As with FlushInstructionCache, what’s important is not what it performs, but just the fact that you called it.

就像 FlushInstructionCache 一样,重点不在它做了什么,而在于你调用了它这件事上。

Recall that merely listing a lib file in your dependencies doesn’t actually cause your program to be bound to the corresponding DLL. You have to call a function in that DLL in order for there to be an import entry for that DLL. And InitCommonControls is that function.

回想一下,只是将某个库文件列在你的依赖列表里,并不意味着你的程序就与对应的DLL绑定了。你得调用这个DLL中的某个方法,才能保证其入口点的存在,而 InitCommonControls 做的就是这件事。

Without the InitCommonControls function, a program that wants to use the shell common controls library would otherwise have no reference to COMCTL32.DLL in its import table. This means that when the program loads, COMCTL32.DLL is not loaded and therefore is not initialized. Which means that it doesn’t register its window classes. Which means that your call to the CreateWindow function fails because the window class has not been registered.

没有对 InitCommonControls 的调用,要使用系统外壳通用控件库的程序,其导入表中就不存在对 COMCTL32.DLL 的引用,这就意味着当程序加载时,COMCTL32.DLL 并没有被加载,因此也没有被初始化,也就意味着没有注册其窗口类,最终意味着当你调用 CreateWindow 时会失败,因为窗口类尚未被注册。

That’s why you have to call a function that does nothing. It’s for your own good.

这就是为什么你需要调用一个什么也不做的方法的原因——这是为你好。

(Of course, there’s the new InitCommonControlsEx function that lets you specify which classes you would like to be registered. Only the classic Windows 95 classes are registered when COMCTL32.DLL loads. For everything else you have to ask for it explicitly.)

(当然了,后来还有个 InitCommonControlsEx 允许你指定要注册哪些类。当 COMCTL32.DLL 加载时,只有传统的 Windows 95 类是默认注册的,要想用到其它的类,你必须进行明确的指定。)

TONT 34923 有关『文件系统穿隧』功能的传闻

原文链接:https://devblogs.microsoft.com/oldnewthing/20050715-14/?p=34923

One of the file system features you may find yourself surprised by is tunneling, wherein the creation timestamp and short/long names of a file are taken from a file that existed in the directory previously. In other words, if you delete some file “File with long name.txt” and then create a new file with the same name, that new file will have the same short name and the same creation time as the original file. You can read this KB article for details on what operations are sensitive to tunnelling.

文件系统中有一个功能可能会让你感到惊讶,这个功能叫做『穿隧』,即某文件的创建时间戳和短、长文件名都来自于该目录中之前存在过的文件。换句话说,如果删掉一个类似『File with logn name.txt』(译注:意为『具有长文件名的文件.txt』)这样的文件,然后新建一个具有相同名称的文件,那么新建的文件会与原有的文件具有相同的短文件名(译注:8.3格式的文件名)和相同的创建时间。你可以阅读这篇知识库文章(译注:KB172190,链接已失效)来了解有哪些操作受这种穿隧功能的影响。

Why does tunneling exist at all?

那么,为什么会有这种功能存在呢?

When you use a program to edit an existing file, then save it, you expect the original creation timestamp to be preserved, since you’re editing a file, not creating a new one. But internally, many programs save a file by performing a combination of save, delete, and rename operations (such as the ones listed in the linked article), and without tunneling, the creation time of the file would seem to change even though from the end user’s point of view, no file got created.

当你用某个程序编辑某现存的文件,然后保存,你会下意识认为文件的创建时间保持不变,毕竟你是在编辑旧文件,而不是创建新文件。然而,在很多程序内部,保存文件的过程实际上是保存、删除和重命名操作的组合(译注:建立一个临时文件、将内容保存到临时文件中、删除旧文件、将临时文件的文件名修改为旧文件)(比如上文链接中列出的程序(译注:链接已失效,无法验证列出了哪些程序))。假使没有穿隧功能,文件的创建时间看上去就发生了改变,即使从用户的角度看来并没有创建任何新文件。

As another example of the importance of tunneling, consider that file “File with long name.txt”, whose short name is say “FILEWI~1.TXT”. You load this file into a program that is not long-filename-aware and save it. It deletes the old “FILEWI~1.TXT” and creates a new one with the same name. Without tunnelling, the associated long name of the file would be lost. Instead of a friendly long name, the file name got corrupted into this thing with squiggly marks. Not good.

有关穿隧功能的重要性,再来看另一个例子。假设有一个文件叫『File with long name.txt』,其对应的短文件名为『FILEWI~1.TXT』。现在在一个不支持长文件名的程序中加载它,然后保存,结果是程序删掉了旧的FILEWI~1.TXT,然后创建了一个具有相同文件名的新文件。没有穿隧功能的话,与文件相关联的长文件名就不见了(译注:如前所述,程序不支持长文件名,所以不可能处理与长文件名相关的事务)。现在文件原来漂亮的长文件名不见了,而是变成了一个带着波浪线的短文件名,这可不好。

But where did the name “tunneling” come from?

话说回来,『穿隧』这个名字是哪来的呢?(译注:File system tunneling 没有官方中文译名,此处译文仅供参考)

From quantum mechanics.

来自量子力学。

Consider the following analogy: You have two holes in the ground, and a particle is in the first hole (A) and doesn’t have enough energy to get out. It only has enough energy to get as high as the dotted line.

请看如下类比:地上有两个洞,一个粒子在A洞中,并且其没有足够的能量跃出洞外,其能量最多只够到达虚线的高度(译注:可能是指图中半高处的灰色线)。

You get distracted for a little while, maybe watch the Super Bowl halftime show, and when you come back, the particle somehow is now in hole B. This is impossible in classical mechanics, but thanks to the wacky world of quantum mechanics, it is not only possible, but actually happens. The phenomenon is known as tunneling, because it’s as if the particle “dug a tunnel” between the two holes, thereby allowing it to get from one hole to another without ever going above the dotted line.

你只是一会儿没看它,可能是去看了会超级碗半场秀,等你回来的时候,这个粒子已经不知怎么进到右边的洞里(译注:直译写法在中文中不雅……理解就行)去了。这在经典力学中是不可能发生的事情,但感谢量子力学的光怪陆离,这不光可能发生,也会实际发生。这种现象被叫做『穿隧』,就好像粒子在两个洞之间『打了一条通道』,使其而需要上升到虚线的高度,就能从一个洞跃进另一个洞。

In the case of file system tunneling, it is information that appears to violate the laws of classical mechanics. The information was destroyed (by deleting or renaming the file), yet somehow managed to reconstruct itself on the other side of a temporal barrier.

而在文件系统中,穿隧则表现为信息看似打破了经典力学的机制:信息已被销毁(通过删除或重命名文件),但却成功在屏障的另一面重建了其自身。

The developer who was responsible for implementing tunneling on Windows 95 got kind of carried away with the quantum mechanics analogy: The fragments of information about recently-deleted or recently-renamed files are kept in data structures called “quarks”.

负责为 Windows 95 开发穿隧功能的开发者捎带着将量子力学的概念带了过来:刚刚删除或重命名过的文件的信息碎片,保存在了被成为『夸克』的数据结构中。

TONT 35013 SYSTEM_FONT 和 DEFAULT_GUI_FONT 是什么?

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

Among the things you can get with the GetStockObject function are two fonts called SYSTEM_FONT and DEFAULT_GUI_FONT. What are they?

在使用 GetStockObject 获取到的对象中,有两个字体分别叫 SYSTEM_FONT 和 DEFAULT_GUI_FONT,它们是什么字体呢?

They are fonts nobody uses any more.

这两个是已经无人在用的字体。

Back in the old days of Windows 2.0, the font used for dialog boxes was a bitmap font called System. This is the font that SYSTEM_FONT retrieves, and it is still the default dialog box font for compatibility reasons. Of course, nobody nowadays would ever use such an ugly font for their dialog boxes. (Among other things, it’s a bitmap font and therefore does not look good at high resolutions, nor can it be anti-aliased.)

回到 Windows 2.0 那时候,用于对话框的字体是一个叫 System 的位图字体,它是 SYSTEM_FONT 所指向的字体,也仍然为了向下兼容而保留用作对话框默认字体。当然,现在已经没有人再去将这么丑陋的字体用在自己的对话框上了。(除此之外,这是个位图字体,所以在高分辨率下观感不佳,也无法被抗锯齿处理。)

DEFAULT_GUI_FONT has an even less illustrious history. It was created during Windows 95 development in the hopes of becoming the new default GUI font, but by July 1994, Windows itself stopped using it in favor of the various fonts returned by the SystemParametersInfo function. Its existence is now vestigial.

DEFAULT_GUI_FONT 则有个不那么出名的故事,它是在 Windows 95 开发过程中创造出来的,原本被寄希望于用作新的默认GUI字体,但到了1994年7月,Windows 已经不再去调用这个别名了,而是使用 SystemParametersInfo 返回的几个字体,而它就变成了(Windows)进化过程中的残余。

One major gotcha with SYSTEM_FONT and DEFAULT_GUI_FONT is that on a typical US-English machine, they map to bitmap fonts that do not support ClearType.

还有一条关于 SYSTEM_FONT 和 DEFAULT_GUI_FONT 的常见技巧用法是,在常见的美国英语语言机器上,它们通常都指向不支持 ClearType 的位图字体。

TONT 35193 为什么在Windows中有基于广播的消息机制?

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

Many Windows information mechanisms are based on message broadcasts, among them DDE, WM_FONTCHANGE, and changes in system settings. Why do these mechanisms use broadcasts, when we know that broadcasts can result in the system grinding to a halt due to windows that have stopped processing messages?

许多Windows中的信息机制都基于消息广播,其中包括DDE、WM_FONTCHANGE,以及系统设置的变更等。为什么这些机制在知晓可能会遇到已经停止处理消息的窗口,而将整个系统拖入挂起状态的前提下,还是要使用广播机制呢?

Because in 16-bit Windows, you didn’t have this problem.

因为在16位Windows环境下,这个问题是不存在的。

Recall that 16-bit Windows was co-operatively multi-tasking. When a program received control of the CPU, it could do anything it wanted, knowing that no other programs could run until it explicitly yielded control by calling a function such as GetMessage or PeekMessage. The downside of this, of course, was that a single hung program caused the entire system to hang, because it wasn’t releasing the CPU. The upside, however, was that if your program was running, then you knew, a priori, that there were no hung programs in the system. How do you know that? Because if there were a hung program, it would be running and not you. If there’s only one thing, and you have it, then you know that nobody else is hogging it. Therefore, broadcasting messages was completely safe in 16-bit Windows. You didn’t have to worry about non-responsive programs because you had proof that there weren’t any.

回忆一下,16位Windows是协作多任务机制。当某个程序获得了CPU的控制权后,它就可以想做什么做什么,因为它知道直到调用类似GetMessage或PeekMessage这样的方法来让渡(对CPU的)控制权之前,没有其它程序是可以同时运行的。这种设计的不足之处,在于一个程序挂起就会导致整个系统挂起,因为它没有释放对CPU的控制权。而这种设计的益处,则在于如果你的程序在正常运行,那么就可以先知先觉地知晓系统中没有其它挂起的程序。何以见得呢?因为如果如果有挂起的程序的话,那肯定是其它正在运行的程序、并且肯定不是你。如果某样东西只有独一份,而此时它在你的掌控下,你就知道肯定没有其它人在占有它。因此,广播机制在16位Windows环境下是绝对安全的,你不用担心有未响应的程序,因为你有证据证明没有这回事。

Of course, when the switch to pre-emptive multi-tasking occurred, this assumption no longer applied, but by then it was too late. The broadcast-based model was already in use, and consequently had to be preserved for compatibility reasons. (It would be bad if, for example, Lotus 1-2-3 stopped working on Windows NT because DDE broadcasts were no longer supported. If the Windows NT team had tried that gambit, nobody would have upgraded and Windows NT wouldn’t have survived to make a second version.)

自然,当抢占式多任务出现后,这样的猜测就再也无法成立了,但那时已经太晚了。基于广播的模型已经广泛应用,并且基于兼容性的原因还得予以保留。(举例来说,如果 Lotus 1-2-3(译注:1990年代流行的办公软件)由于 Windows NT 不再支持 DDE 广播而无法是用了,那将是一件很糟糕的事。如果 Windows NT 团队真这样下注的话,是不会有人为此而升级系统的,而 Windows NT 连活到第二个版本的机会都没有。)

On the other hand, given the risks involved in DDE broadcasts, you probably would be better off designing your program to not use dynamic data exchange as a data communication mechanism, thereby avoiding the pitfall of message broadcasts. No point contributing to the problem.

另一方面,由于DDE广播中存在的这些风险,你大概应当选择不要使用动态数据交换(DDE)作为你的应用的数据通讯机制,这样就可以避免由于消息广播(的缺点)而产生的坑了。为这种问题添砖加瓦是没有意义的。