在Windows操作系统中,资源管理器(Explorer)是一个强大的工具,它允许用户浏览和管理文件系统。但知道吗?它还可以通过注册特定的URL前缀来扩展其功能,从而支持自定义的文件系统。例如,Microsoft就利用这一特性实现了FTP文件夹的集成。
要实现这一点,需要在注册表中添加自己的URL前缀。具体来说,需要复制并修改位于HKEY_CLASSES_ROOT\ftp
中的条目。但这里有一个奇怪的现象:不会在资源管理器中看到一个名为"ftp文件夹"的根项目,所有的FTP文件夹都直接以"Internet Explorer"项目作为根。
这种设计意味着"Internet Explorer"项目必须能够理解所有底层命名空间的pidls(项目标识符列表)。为了解决这个问题,Internet Explorer采用了一种特殊的机制,即IDelegateFolder
接口。
通过IDelegateFolder
接口,命名空间扩展将获得一个IMalloc
接口。这个接口的Alloc
函数会分配一个指向命名空间扩展的Internet Explorer pidl,并预留空间以插入自己的pidl。
下面是IDelegateFolder
接口的IID定义:
DEFINE_GUID(IID_IDelegateFolder,
0xADD8BA80L,
0x002B,
0x11D0,
0x8F,
0x0F,
0x00,
0xC0,
0x4F,
0xD7,
0xD0,
0x62);
下面是IDelegateFolder
接口的定义:
DECLARE_INTERFACE_(IDelegateFolder, IUnknown)
{
// IUnknown methods
STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
// IDelegateFolder methods
STDMETHOD(SetItemAlloc)(THIS_ IMalloc *pMalloc) PURE;
};
当命名空间扩展被实例化后,Internet Explorer会查询IDelegateFolder
接口,并调用SetItemAlloc
方法,传递一个IMalloc
接口。必须存储这个接口。
从这一刻起,每当需要创建一个pidl时,必须遵循以下步骤:
IMalloc
的Alloc
函数。返回的缓冲区将已经是一个pidl,以2字节的大小开始,然后是一个2字节的签名(0x61 0x03)。所有传递到命名空间扩展的pidls也将有这种格式。这意味着将在偏移量4处找到自己的pidl。
pidls仍然使用标准的shell分配器进行释放。如果命名空间扩展有子文件夹,那么这些子文件夹将遵循正常的系统规则。列表中的第一个id将是特殊的Internet Explorer pidl,所有随后的都是自己的标准pidls。
这不是Microsoft选择的一个干净解决方案。如果Internet Explorer根节点能够执行嵌入pidl的插入和提取,那么就可以消除对这个接口的需求,这将会更加简单。
通过这种方式,可以扩展Windows资源管理器的功能,实现自定义的文件系统。这不仅增加了资源管理器的灵活性,也为开发者提供了更多的创新空间。