因为shell扩展处理程序在系统进程中运行,即shell进程,Windows NT管理员需要控制哪些shell处理程序被允许运行。管理员可以控制哪些shell处理程序可以以与现在可以控制哪些设备驱动程序可以运行相同的方式运行。
对于Windows NT shell来识别和运行一个shell扩展处理程序,您必须遵循注册Shell扩展中的说明,然后处理程序的CLSID也必须列在另一个新的注册表项下。该注册表项包含一个允许shell运行的处理程序的列表。默认情况下,此密钥的访问控制权限仅允许具有管理员权限的人员修改列表。
扩展程序的CLSID必须在以下位置注册:
HKEY_LOCAL_MACHINE \\\\ Software \\\\ Microsoft \\\\ Windows \\\\ CurrentVersion \\\\ Shell Extensions \\\\ Approved
要注册扩展名,应将“命名值”添加到“已批准”键。该值的名称必须是从StringFromCLSID()函数获取的CLSID的字符串形式,该函数在注册表中的其他位置使用。值本身应该是ProgID。ProgID存储在这里只是简单地检查注册表,因为它比CLSID更容易解密。然而,只有在CLSID存在或不存在的情况下,Windows NT shell不会查看此值。
您的设置应用程序可能也可能无法写入此密钥,具体取决于安装应用程序的人员的权限。设置应用程序应尝试打开上述键,请求KEY_SET_VALUE权限。如果成功,可以添加新的CLSID来完全注册相应的shell扩展。如果请求失败并发生安全违规,则安装应用程序的人员无权注册新的扩展。在这种情况下,设置应用程序可能会警告用户某些应用程序功能将不可用,除非管理员将其打开(通过安装应用程序或直接写入注册表项)。或者,如果shell扩展对应用程序的功能至关重要,则安装应用程序可能会导致安装失败,通知用户程序必须由管理员进行安装。
当在Windows 95上设置时,不必将CLSID写入此键,尽管写入它是无害的。但是请注意,Windows 95安装中可能不存在密钥,因此如果安装应用程序确实尝试打开该密钥,则可能会失败。
以下示例代码详细说明了此过程。完全错误处理已省略。
#include < windows.h >
#include < string.h >
void main(void)
{
//
//首先尝试打开批准的扩展名的注册表项
//上市请注意第二个参数(的
//注册表路径字符串)。
//
long err;
HKEY hkApproved;
err = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
“Software \\\\ Microsoft \\\\ Windows \\\\ CurrentVersion \\\\ Shell Extensions \\\\ Approved”,
0,
KEY_SET_VALUE,
&hkApproved);
if (err == ERROR_ACCESS_DENIED)
{
//
//用户没有权限向该键添加新值。在这个
//的情况下,合理的动作就是向用户发出一些警告
//应用程序功能将不可用,除非管理员
//安装应用程序。如果shell扩展是中心的
//应用程序的功能,告诉用户安装
//只能由管理员执行,并停止安装。
//
}
else if (err == ERROR_FILE_NOT_FOUND)
{
//
//键不存在。这只有在安装程序运行时才会发生
//在Windows 95而不是Windows NT上,或者如果您在较旧版本上安装
//没有新shell的操作系统的版本。
//
}
else if (err != ERROR_SUCCESS)
{
//
//其他一些问题
//
}
其他
{
//
//该键的打开成功。现在注册新的shell扩展
//在这个键下这需要具有ProgID和字符串形式的
// CLSID方便。
//
//
//假设lpstrProgID包含我们的ProgID字符串。
//
LPSTR lpstrProgID = "My Bogus Class";
//
//假设clsidExtension包含CLSID结构体。下面的代码
//从此CLSID创建一个字符串。如果是一个字符串版本
// CLSID已经很方便,跳过这个代码。
//
CLSID clsidExtension = {0x11111111, 0x1111, 0x1111, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
HRESULT hr;
LPOLESTR lpolestrCLSID;
CHAR rgchCLSID[40];
CoInitialize(NULL);
hr = StringFromCLSID(clsidExtension, &lpolestrCLSID);
//
// StringFromCLSID返回Unicode字符串,因此转换为ANSI
//调用注册表。请注意,在Windows NT上,您可以调用Unicode
//版本的注册表API。
//
WideCharToMultiByte(CP_ACP,0,lpolestrCLSID,-1,rgchCLSID,40,
NULL, NULL);
CoTaskMemFree(lpolestrCLSID);
CoUninitialize();
//
//现在将新值添加到注册表。
//请注意,每个新的shell扩展名CLSID必须在这里注册。
//
err = RegSetValueEx(
hkApproved,
rgchCLSID,
0,
REG_SZ,
(const BYTE *)lpstrProgID,
strlen(lpstrProgID));
//
//最后关闭键。
//
err = RegCloseKey(hkApproved);
}
}