The Structure of Registry Entries
The following Registry structure is required if QUIKVIEW is to
associate a file's class identifier or extension with the class
identifier of a file viewer. If you deviate from this structure,
QUIKVIEW won't find your file viewer, and you'll be one
frustrated developer.
HKEY_CLASSES_ROOT
\QuickView
\<extension> = <human-readable document type>
\{<CLSID>} = <human-readable viewer name>
\{<CLSID>} = <human-readable viewer name>
\{<CLSID>} = <human-readable viewer name>
§
[More extension entries for additional file types]
§
\CLSID
\{<CLSID>} = <human-readable viewer name>
\InprocServer32 = <full path to file viewer DLL>
\ThreadingModel = <Model>
§
[More class IDs for file viewers and other object servers]
§
How about some explanation?
- HKEY_CLASSES_ROOT is the root of the Registry.
- The QuickView key is the top-level key, where the file
viewer associations are stored. It can have any number of
extension subkeys (TXT, CPP, and so on), each
representing a registered file type. Each extension
subkey can have one or more class identifier subkeys,
each representing a registered file viewer object. The
most recently registered file viewer appears first in the
list of class identifier subkeys, and it is the first one
found when QUIKVIEW enumerates the registered file
viewers.
- The <extension> key is a three-character
file extension preceded by a period (for example, .WRI).
- The <human-readable document type> key is a
string that can be displayed to the user, describing the
file type associated with the class identifier or
extension. A file viewer can change this string when it
is installed so that the name always reflects the
preferred viewer. For example, this string might be Windows
Write Document.
- The CLSID key is a 16-byte OLE class identifier spelled
out in hexadecimal digits in the form
12345678-1234-1234-1234-1234567890AB, including hyphens.
All class identifiers are surrounded by curly braces
( { } ) when stored in the Registry. The file
viewer class identifier should always differ from the
file type class identifier because the application that
created the file might already be using the file type
class identifier to identify itself as a compound
document server.
- The <human-readable viewer name> key is a
string that describes the vendor of the file viewer, as
such a description might be displayed in an About
boxCompany ABC Write Document Viewer, for
instance.
- The <Model> subkey specifies the threading
model as it relates to OLE objects. Under Windows 95, OLE
is apartment-threaded. The term apartment
describes a thread with a message queue that supports
OLE/COM (Component Object Model) objects. Operations that
yield to the message queue can cause further messages to
be sent to any objects within the apartment. Apartment
model threading simply allows multiple apartments where
previously only one existed (the main application
thread). By default, a single-threaded application
consists of a single apartment (its single thread). When
a process calls CoInitialize or OleInitialize from a
thread, a new OLE apartment is created. Thereafter, each
time CoInitialize or OleInitialize is called in a thread,
a new OLE apartment is created. You can create in-process
objects that are apartment-model-aware in any apartment.
You mark the DLL as apartment-model-aware through the ThreadingModel=Apartment
value of the InprocServer32 key. In-process objects that
are not apartment-model-aware are created in the main
apartment of the application, the main apartment being
the first thread that calls CoInitialize or
OleInitialize.
Each CLSID stored under the file extension subkeys corresponds
to an entry of that same CLSID stored under the top-level key,
called (what else?) CLSID, the standard location for storing
information about OLE objects. For file viewers, an
InprocServer32 subkey is needed under the file viewer's class
identifier key. The value of this subkey is the full path to the
file viewer DLL. In my sample, the file viewer is stored in the
\WINDOWS\SYSTEM\VIEWERS folder. InprocServer32 is a standard OLE
subkey storing the path to an object. Using this subkey allows
the QUIKVIEW program to use standard OLE APIs to access and
create objects from file viewer servers.
An apartment-model-aware process must have thread-safe entry
points because multiple apartments can call CoCreateInstance or
CoGetClassOb-ject simultaneously. In practice, this means that
your application should do the following:
- DllGetClassObject must support supplying references to
multiple class objects. If you implement your class
objects dynamically, this shouldn't be an issue because
any class object you supply will be called only from a
single apartment. If you implement your class object as a
static object, you must ensure that your AddRef and
Release member functions use InterlockedIncrement and
InterlockedDecrement rather than the ++/-- operators.
- With both static and dynamic class objects, global
lock-count, as implemented for IClassFactory::LockServer,
must use InterlockedIncrement and InterlockedDecrement.
If you're not using a global counter for this value now,
you should start doing so.
- Carefully implement DllCanUnloadNow by using the global
counter from InterlockedIncrement along with a global
counter that keeps track of the total number of instances
that have been created.
When you create a file viewer using MFC, you can let MFC
initialize for you, as I did in the MFCVIEW sample.