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)作为你的应用的数据通讯机制,这样就可以避免由于消息广播(的缺点)而产生的坑了。为这种问题添砖加瓦是没有意义的。

Day 11599 在Debian 10上安装Dell OpenManage

环境为Debian 10默认安装。

1、为PATH变量增加/usr/sbin(永久修改位置为/etc/login.defs):

export PATH=$PATH:/usr/sbin

2、在root下运行以下指令安装OpenManage软件包(来自此Reddit帖子,感谢作者):

gpg –keyserver hkp://pool.sks-keyservers.net:80 –recv-key 1285491434D8786F
gpg -a –export 1285491434D8786F | apt-key add –
echo “deb http://linux.dell.com/repo/community/openmanage/930/bionic bionic main” > /etc/apt/sources.list.d/linux.dell.com.sources.list
wget http://archive.ubuntu.com/ubuntu/pool/universe/o/openwsman/libwsman-curl-client-transport1_2.6.5-0ubuntu3_amd64.deb
wget http://archive.ubuntu.com/ubuntu/pool/universe/o/openwsman/libwsman-client4_2.6.5-0ubuntu3_amd64.deb
wget http://archive.ubuntu.com/ubuntu/pool/universe/o/openwsman/libwsman1_2.6.5-0ubuntu3_amd64.deb
wget http://archive.ubuntu.com/ubuntu/pool/universe/o/openwsman/libwsman-server1_2.6.5-0ubuntu3_amd64.deb
wget http://archive.ubuntu.com/ubuntu/pool/universe/s/sblim-sfcc/libcimcclient0_2.2.8-0ubuntu2_amd64.deb
wget http://archive.ubuntu.com/ubuntu/pool/universe/o/openwsman/openwsman_2.6.5-0ubuntu3_amd64.deb
wget http://archive.ubuntu.com/ubuntu/pool/multiverse/c/cim-schema/cim-schema_2.48.0-0ubuntu1_all.deb
wget http://archive.ubuntu.com/ubuntu/pool/universe/s/sblim-sfc-common/libsfcutil0_1.0.1-0ubuntu4_amd64.deb
wget http://archive.ubuntu.com/ubuntu/pool/multiverse/s/sblim-sfcb/sfcb_1.4.9-0ubuntu5_amd64.deb
wget http://archive.ubuntu.com/ubuntu/pool/universe/s/sblim-cmpi-devel/libcmpicppimpl0_2.0.3-0ubuntu2_amd64.deb
dpkg -i libwsman-curl-client-transport1_2.6.5-0ubuntu3_amd64.deb
dpkg -i libwsman-client4_2.6.5-0ubuntu3_amd64.deb
dpkg -i libwsman1_2.6.5-0ubuntu3_amd64.deb
dpkg -i libwsman-server1_2.6.5-0ubuntu3_amd64.deb
dpkg -i libcimcclient0_2.2.8-0ubuntu2_amd64.deb
dpkg -i openwsman_2.6.5-0ubuntu3_amd64.deb
dpkg -i cim-schema_2.48.0-0ubuntu1_all.deb
dpkg -i libsfcutil0_1.0.1-0ubuntu4_amd64.deb
dpkg -i sfcb_1.4.9-0ubuntu5_amd64.deb
dpkg -i libcmpicppimpl0_2.0.3-0ubuntu2_amd64.deb

apt update
apt install srvadmin-all
touch /opt/dell/srvadmin/lib64/openmanage/IGNORE_GENERATION
srvadmin-services.sh enable && srvadmin-services.sh start

3、此时已可通过https://IP:1311/看到网页界面,但命令行omreport功能暂时不可用,会提示:

omconfig: error while loading shared libraries: libxslt.so.1: cannot open shared object file: No such file or directory

执行以下指令安装所缺失的libxslt1.1:

apt-get install libxslt1.1

此时执行omreport的查询命令(如omreport system summary),会提示(即使在root下执行也是如此):

Error! User has insufficient privileges to run command.

依据此处内容提示(帖子下方的回复),应为缺失libncurses5,运行如下指令安装之,并重启OpenManage相关服务:

apt install libncurses5

systemctl start dsm_sa_datamgrd
systemctl start dsm_sa_eventmgrd
systemctl start dsm_sa_snmpd
systemctl start dsm_om_connsvc
systemctl start dsm_om_shrsvc

现在终于可以使用omreport在CLI下查看系统概况了。