Windows 95的用户界面代码是如何移植到Windows NT的?
How did the Win 95 user interface code get brought to the Windows NT code base?

原始链接: https://devblogs.microsoft.com/oldnewthing/20251028-00/?p=111733

将 Windows 95 用户界面带到 Windows NT 4.0 是一个复杂的工程,涉及两个团队的紧密合作。虽然定期的沟通让 NT 团队了解 Windows 95 的开发情况,但 NT 团队在后期移植过程中发挥了更积极的作用。 窗口管理器很大程度上是*重新实现*的,以 Windows 95 代码为参考,因为与它们共同的 Windows 3.1 祖先相比,代码差异很大。像 Explorer 这样的组件更直接地*合并*,但需要大量的更新——特别是从 `CHAR` 过渡到 Unicode,这需要像创建 `IShellLinkA` 和 `IShellLinkW` 接口这样的更改。 至关重要的是,更改是双向的。NT 的修复程序被反馈回 Windows 95 代码库,受到 `#ifdef` 指令和巧妙的宏(如 `TCHAR` 和自定义 `SIZEOF` 宏)的保护,以跟踪兼容性验证。这确保了现有 Windows 95 用户的稳定性。 整个过程因其源代码控制系统“SLM”的限制而变得复杂,该系统缺乏分支功能,需要为每次文件更改手动进行三方合并。

这个Hacker News讨论围绕着Windows用户界面的复杂历史,特别是Windows 95的代码如何整合到Windows NT代码库中。原始链接指向一篇微软开发者博客,详细介绍了这个过程。 用户们回忆起早期Windows版本的怪癖,并指出古老UI的残余在现代设置中仍然可见。一个关键主题是微软似乎在限制用户配置选项,推动用户使用组策略,同时在没有Active Directory的情况下难以支持庞大的用户群。 对话延伸到版本控制(如CVS和SourceSafe等Git之前的工具)、Unicode实现挑战(UTF-8与UTF-16)以及Git作为标准出现的时间相对较晚等讨论。许多评论者分享了在现代工具出现之前的软件开发和维护的困难经历。 还有人幽默地调侃`explorer.exe`至今仍会偶尔卡死。最后,有人请求改进Hacker News对这个特定微软开发者博客的域名高亮显示。
相关文章

原文

A long time ago, somebody asked, “How did the new Windows 95 user interface get brought to the Windows NT code base? The development of Windows 95 lined up with the endgame of Windows NT 3.1, so how did the finished Windows 95 code get brought to the Windows NT code base for Windows NT 4.0? Did they reimplement it based on the existing specification? Was the code simply merged into the Windows NT code base?”

Members of the Windows 95 user interface team met regularly with members of the Windows NT user interface team to keep them aware of what was going on and even get their input on some ideas that the Windows 95 team were considering. The Windows NT user interface team were focused on shipping Windows NT, but they appreciated being kept in the loop.

During the late phases of the development of Windows 95, the Windows NT side of the house took a more active role in bringing the Windows 95 user interface to Windows NT. They started implementing the new window manager features that Windows 95 introduced, both in terms of new functions such as Register­Class­Ex and Set­Scroll­Info, as well as new behaviors such as having a Close button in the upper right corner. The window managers on Windows NT and Windows 95 both had ancestry in the Windows 3.1 window manager, so a lot of the designs were the same, but the code had long since diverged significantly, so it wasn’t so much merging the code as it was using the Windows 95 code as a reference implementation when reimplementing the features on Windows NT. (For example, the algorithm for walking the dialog tree in the face of WS_EX_CONTROL­PARENT remained the same, but the expression of the algorithm was different.)

The code for Explorer and other user-model components had an easier time. They were taken as-is into the Windows NT code base, warts and all, and the copy was then updated in-place to be more Windows NT-like. For example, the Windows 95 shell used CHAR as its base character, but Windows NT was Unicode-based, so the Windows NT folks had to replace CHAR to WCHAR, and they had to create Unicode variants of the existing shell interfaces, which is why we have IShellLinkA and IShellLinkW, for example. This in turn exposed other problems, such as code that used sizeof(stringBuffer) to calculate the size of a CHAR string buffer, that now had to be changed to sizeof(stringBuffer) / sizeof(stringBuffer[0]) so that it returned the number of elements in the buffer rather than the number of bytes.

Whereas the window manager changes were one-way ports (from Windows 95 into Windows NT), the Explorer and other user-mode changes were bidirectional. The Windows NT team merged their changes back into the Windows 95 code base, so that when they took the next drop of the Windows 95 code base, they wouldn’t have to go back and fix the things that they had already fixed.

Since the code went back to Windows 95, all of the Windows NT-side changes had to be arranged so that they would have no effect on the existing Windows 95 code. The Windows NT team didn’t want to introduce any bugs into the Windows 95 code as part of their port. Protecting the changes was done in a variety of ways.

One was to enclose all the new code inside #ifdef WINNT directives so that they weren’t compiled by Windows 95, or #ifdef#else#endif blocks if the Windows NT version had to diverge from the Windows 95 version. Another was to use macros and typedefs like TCHAR and LPCTSTR so that the same code could compile both as Windows 95 and Windows NT, but using different base characters.

In the case of sizeof directives, a change from sizeof(stringBuffer) to sizeof(stringBuffer) / sizeof(stringBuffer[0]) has no effect on Windows 95 because the sizeof(stringBuffer[0]) is 1, and dividing by 1 has no effect, so that change could be left without protection. But the Windows NT team had another problem: How would they know whether a particular sizeof was one that had already been vetted for Windows NT compatibility, as opposed to one that came from fresh code changes to Windows 95 that need to be inspected? Their solution was to define a synonym macro

#define SIZEOF sizeof

When the Windows NT team verified that a sizeof was correct, or when they fixed it to be correct, they changed the sizeof to SIZEOF. That way, they could search the code for lowercase sizeof to see what still had yet to be inspected. (The Windows 95 team were told to continue using sizeof in new code, so as not to mess up this convention.)

Now, all this happened decades ago when Microsoft used an internal source code system known as SLM, pronounced slime. Formally, it stood for Source Library Manager, but nobody knew that. We just called it SLM. SLM did not support branches, so moving changes from Windows 95 to Windows NT involved manually doing three-way merges for all of the files that changed since the last drop. I suspect that this manual process was largely automated, but it was not as simple as a git merge.

Bonus chatter: The team responsible for porting the Windows 95 shell to Windows NT included Dave Plummer, host of the YouTube channel Dave’s Garage. They had custom business cards made which they used as calling cards. On one side was the email aliases of the team members, arranged in an attractive pattern. On the other side was the simple message: “You have been visited.”

联系我们 contact @ memedata.com