User Interface Extensions and Windows NT

You can use Windows 95 user interface extensions under Microsoft Windows NT version 3.51 running with its new shell. (The shell is still due to be released as of this writing.) You will, however, need to place the extension DLL in \WINDOWS\SYSTEM32 rather than in \WINDOWS\SYSTEM. You'll also need to add one step in your application's setup process and registration.

To have Windows NT recognize and run your user interface extension, the handler's CLSID must be listed under a new Registry key that contains a list of approved handlers. By default, only a person with administrator privileges is allowed to modify the list in this key. Here is the location where the CLSID must be registered in Windows NT:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\
Shell Extensions\Approved

To register the extension, you must add a named value to the Approved key. The name of the value must be the string form of the CLSID, which you can obtain by using the StringFromCLSID function.

If you haven't yet written applications for Windows NT, you might find it odd that your setup application would be unable to write to the Approved key. The ability to write to this key depends on the access privileges of the person installing the application. The setup application should attempt to open the key, requesting the KEY_SET_VALUE permission. If it succeeds, you can add the new CLSID to fully register the corresponding extension. If the request fails, with a security violation, the person installing the application does not have permission to register new extensions. In this case, the setup application might warn the user that some application features will not be available unless an administrator turns them on (by installing the application or by writing the Registry keys directly). Or, if the extension is crucial to the application's functioning, the setup application might cause the installation to fail completely, notifying the user that an administrator must install the program.

The following sample code demonstrates how an application can register its user interface extension under Windows NT:

// First, attempt to open
// the Registry key where
// approved extensions are listed.
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)
{
// The user does not have permission to add a new value
// to this key. In this case, you might warn the user that some
// application features will not be available unless an administrator
// installs the application. If the extension is central to the
// application's functioning, tell the user that only an
// administrator can perform the install, and stop the install.
§
}
else if (err == ERROR_FILE_NOT_FOUND)
{
// The key does not exist. This happens only if setup is running
// on Windows 95 instead of Windows NT or if you are installing on an
// older version of either operating system that lacks the Win95 UI.
§
}

else if (err != ERROR_SUCCESS)
{
// Some other problem...
}

else
{
// Assume that lpstrProgID contains your ProgID string.
LPSTR lpstrProgID = "My Bogus Class";

// Assume that clsidExtension contains the CLSID structure.
// The following code creates a string from this CLSID.
// If a string version of the CLSID is already handy,
// skip this code.
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 returns a Unicode string, so convert to ANSI for
// calling the Registry. Note that on Windows NT you can call the
// Unicode version of the Registry API instead.
WideCharToMultiByte (CP_ACP, 0, lpolestrCLSID, -1, rgchCLSID, 40,
NULL, NULL);

CoTaskMemFree (lpolestrCLSID);
CoUninitialize ();

// Now add the new value to the Registry.
err = RegSetValueEx (
hkApproved,
rgchCLSID,
0,
REG_SZ,
(const BYTE *)lpstrProgID,
strlen (lpstrProgID));

// Finally, close the key.
err = RegCloseKey (hkApproved);
}

If you are registering your extension for Windows NT version 3.51 (with the new shell) by using a REG file, add the following line:

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\
Shell Extensions\Approved\{CLSID_VALUE}]
@="My Shell Extension"

For CLSID_VALUE, insert the actual CLSID for your extension. For My Shell Extension, substitute the name of the exported user interface extension.