接口也是一种合约

接口 = 合约

接口也是一种合约,但请记住,合同适用于双方。在大多数情况下,当我们阅读接口文档时,都是从接口客户端的角度来看待接口的,但是如果我们能从接口服务器端来理解,则会有意想不到的收获。

角色扮演开始

让我们举个例子:控制面板接口(Interface for control panel)

通常当你有关于控制面板接口的文档的时候,你会认为自己是客户端,比如,文档是这样写的:

当控制面板管理器首次加载”控制面板”应用程序时,它会检索CPIApplet函数的地址,然后使用该地址来调用该函数并传递消息。

下面我们来看看,分别站在不同的角色是如何看待这段接口描述的。

控制面板应用程序:我需要导出一个名为CPIApplet的函数用来接收管理器传过来的信息。

控制面板管理器:我需要使用GetProcAddress来获取客户提供的CPIApplet地址并向它发送消息。

关于消息处理部分,角色扮演如下:

控制面板应用程序:我需要准备好按文档所说的顺序接收消息。

控制面板管理器:我需要准备好按文档所说的顺序发送消息。

文档里还有这么一句:控制面板管理器需要调用FreeLibrary函数来释放控制面板应用程序。

控制面板应用程序:我最好为即将到来的卸载做好准备。

控制面板管理器:我要开始卸载DLL啦。

实际的例子

让我们来写个简单的小程序来演示一下:

除了上面代码中的创建显示窗口和进入消息循环之外,我们的代码表现的就是一个控制面板管理器。我们使用了access.cpl这个控制面板应用程序来作为测试程序。确定好程序的路径之后,我们调用了如下的RunControlPanel函数来执行大部分的工作,如下图所示:

请先忽略上面标红色的部分,后面我们还讨论它们。

我们所做的实际上就是遵循文档里所说的步骤,但是从服务器端的角度来解读。我们加载了DLL,定位了准备调用的函数,使用CPL_INITL来调用这个函数,然后是CPL_GETCOUNT。如果在这个CPL文件中有任何控制面板程序,则我们查询它们的信息并进行了双击操作,最后停止。

以上这些有意思的工作都走了一遍之后,最后我们按照文档的要求执行了清理工作(通过发送CPL_EXIT消息)。

就是这样了,那么,上面标红色的部分是什么回事?

这些是为了支持那些带有自定义清单的控制面板应用程序,它们是在Windows XP里引入的新东西。

如果在控制面板中使用v6版本的ComCtl32或由RunDll32.exe运行的DLL,则你将看到:该应用程序通过将其清单附加为资源号123将其清单提供给控制面板主机。这就是红色代码的作用:它加载并激活清单,然后调用控制面板应用程序执行其操作(此时清单处于活动状态),然后进行清理。如果没有清单,CreateActCtx将返回INVALID_HANDLE_VALUE。我们并不将这个视为错误,因为许多程还没有提供清单。

课后练习题

在调用SearchPath的时候,我们在第一个参数里传入了NULL,这个会有什么安全方面的影响吗?

最后

Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。

本文来自:《You can read a contract from the other side》

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200909A0MW3R00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券