让我们听一则历史小故事,放松一下神经吧。有开发者发现:如果你将动态链接库(以下使用简称DLL)文件命名为security.dll,则会发生奇怪的事情。原因在于:系统DLL里已经有一个同名的文件了,这个DLL是用于系统提供安全方面的接口的组件(Security Support Provider Interface),虽然这个文件现在被命名为了”secur32.dll”,但过去的一段时间,我们曾经使用”security.dll”来作为它的名称。
如果你查看系统文件夹(system32),则你应该会发现该文件夹下有两个文件,一个是”security.dll”,另一个是”secur32.dll”。如果你有个查看DLL导出函数的工具,则你还会发现”security.dll”里的导出函数只是一套对”secur32.dll”的转发调用。如果你查阅相关的MSDN文档,则会发现每个人都在谈论”secur32.dll”,并且几乎没有提及它的兄弟”security.dll”。
在Windows 95那会儿,安全支持提供者接口被实现到两个不同的DLL中。根据当前运行的系统是Windows NT还是Windows 95,决定当前应用程序应该依赖哪一个DLL实现。在Windows 95系统上,它被称为”secur32.dll”,而在Windows NT上,它被称为”security.dll”。这确实给操作系统开发人员带来了不小的困惑和混淆。于是Windows NT开发团队决定”跟随大流”,将它们的安全提供者DLL修改为”secur32.dll”。
这可能是为了应用程序兼容性方面的原因:在Windows 95上运行的应用程序,从来没有在Windows NT上运行测试过,它们会直接尝试加载”secur32.dlL”,而不是根据操作系统的不同来加载正确的DLL文件版本。
好了,让我们回到现在的时间。如果你将你的DLL文件命名为”Security.dll”,会发生什么事情呢?请回忆一下DLL文件搜索顺序。
结果是,在应用程序目录里,如果程序需要”Security.dll”,则它找到的版本是你的版本,而不是操作系统的版本,即使它实际是想调用系统版本的”Security.dll”。这就是为什么当使用你自己版本替换系统版本的Security.dll会导致SSPI错误的原因所在。你的DLL根本就和操作系统的Security.dll不是同一回事,只是凑巧它们的名字一样罢了。
类似的,你如果创建一个名为”DDRAW.DLL”的文件,则也会和系统版本的相冲突,当应用程序尝试创建一个DirectDraw表明时,就会出现问题。”Security.dll”存在的问题是,它有一个十分常见的名称(开发者很容易会给他们自己的DLL起这样一个名字),然而这个DLL提供的系统功能却很少被开发者所了解。(很显然的,如果你在你的应用程序文件夹起了一个名为”kernel32.dll”的DLL文件,则肯定没什么好事发生。)
我的做法是,使用随机字符串对DLL文件进行命名,这样就不会和系统DLL文件相冲突了。但是这样带来的一个弊端是:从文件名上不容易看出这个DLL是干什么用的。还好,这个问题,对我来说,不大。
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。本文来自:《Don’t name your DLL “Security.dll”》