PRB: Registry Overwritten with Same ProgID/Different Bitness Server (145676)
The information in this article applies to:
- Microsoft Visual Basic Standard Edition, 32-bit, for Windows 4.0
- Microsoft Visual Basic Professional Edition, 16-bit, for Windows 4.0
- Microsoft Visual Basic Professional Edition, 32-bit, for Windows 4.0
- Microsoft Visual Basic Enterprise Edition, 16-bit, for Windows 4.0
- Microsoft Visual Basic Enterprise Edition, 32-bit, for Windows 4.0
This article was previously published under Q145676 SYMPTOMS
On a single machine, developing and using 16-bit and 32-bit OLE servers
that provide objects with the same ProgID may cause problems if no
compatible server is specified. Some registry entries will point only to
the last server registered and only this server may be accessible from OLE
Automation clients.
This article illustrates why this behavior occurs, and also explains how to
avoid this problem.
RESOLUTION
If development of both 16-bit and 32-bit servers is done on the same
machine, this problem can be avoided by specifying a compatible server for
your OLE server project. If a compatible server exists, the CLSID from the
compatible server will be used when any new executable is created. In the
above scenario, this means that only one key CLSID will be used for the
server. Instead of one CLSID possessing a LocalServer key and another
containing a LocalServer32 key, both LocalServer and LocalServer32 keys
will exist beneath the same CLSID. When more than one server is listed
beneath a CLSID, OLE has a predefined order that is used to determine which
server is used to provide the object.
MORE INFORMATION
Two of the most important keys that are created by registration of an OLE
server are a ProgID key and a CLSID key. The ProgID is created immediately
beneath the HKEY_CLASSES_ROOT predefined key and consists of the
ProjectName.ClassName for a Visual Basic OLE server. The single key created
beneath this ProgID key is named CLSID; its value is a 64-bit number that
is used by OLE to uniquely identify the particular object. In addition to
the ProgID and file extension keys off of HKEY_CLASSES_ROOT, there is also
a key just named CLSID. Expanding this key will show subkeys for each CLSID
that is registered on the machine. There will be a key with the same 64-bit
number associated with the ProgID in this section. Keys underneath this
individual CLSID hold information that OLE uses to access the server.
When classes provided by a 32-bit out-of-process (EXE) OLE server are
registered, two of the keys created beneath the CLSID for each class are
named LocalServer32 and InprocHandler32. Registration of a 16-bit server
causes the creation of LocalServer and InprocHandler keys. The
InprocHandler key specifies the OLE DLL to be used by the client for
communication with the server. The DLL used by local Visual Basic OLE
servers is OLE2.DLL on 16-bit machines, and OLE32.DLL on 32-bit Windows
operating systems. The LocalServer(32) key contains the path and filename
of the executable for the server. With an out-of-process server created
with Visual Basic, this will be the executable generated by Visual Basic.
The problem addressed by this article occurs when 16-bit and 32-bit
versions of an OLE server are registered and provide objects with the same
ProgID but different CLSIDs. This can easily happen if, for example, a 16-
bit OLE server project is loaded into the 32-bit version of Visual Basic
and a new 32-bit executable is created. Starting with a fresh machine,
registering (via compilation perhaps) a 32-bit server will create these
registry entries (among others):
HKEY_CLASSES_ROOT\ProjectName.ClassName
HKEY_CLASSES_ROOT\ProjectName.ClassName\CLSID = <CLSID for 32-bit server>
and
HKEY_CLASSES_ROOT\CLSID\<CLSID for 32-bit server>
HKEY_CLASSES_ROOT\CLSID\<CLSID for 32-bit server>\LocalServer32
Where LocalServer32 points to the 32-bit executable.
If a client requests an object of ProjectName.ClassName, the 32-bit EXE
will be started and used to provided the object. Now suppose a 16-bit
server is now registered with the same ProgID of ClassName.ProjectName. The
registry will contain these relevant entries (where the ones marked with
asterisks are new or modified):
HKEY_CLASSES_ROOT\ProjectName.ClassName
*HKEY_CLASSES_ROOT\ProjectName.ClassName\CLSID = <CLSID for 16-bit server>
and
*HKEY_CLASSES_ROOT\CLSID\<CLSID for 16-bit server>
*HKEY_CLASSES_ROOT\CLSID\<CLSID for 16-bit server>\LocalServer
HKEY_CLASSES_ROOT\CLSID\<CLSID for 32-bit server>
HKEY_CLASSES_ROOT\CLSID\<CLSID for 32-bit server>\LocalServer32
If a client now requests an object of ProjectName.ClassName, OLE will look
up the ProgID and use the value of the CLSID beneath the ProgID to
determine what object to create. This value is now the CLSID for the 16-
bit server, so the server that will be started to provide the object will
be the EXE pointed to by the LocalServer key of the new CLSID that was
added by the registration of the 16-bit server.
Furthermore, if the 16-bit server is now unregistered, not only will the
newly added CLSID keys be removed, but the ProgID key will be removed also.
At this point the 32-bit server will be unable to provide objects, despite
the fact that it has not been unregistered. Because the ProgID key is gone,
the CLSID keys that the 32-bit server added are orphaned and OLE has no way
to access them. Reregistering the 32-bit server will add the correct ProgID
and enable the 32-bit server to again provide objects.
Steps to Reproduce- Start Visual Basic 4.0, 16-bit. Form1 is created by default.
- From the Insert menu, choose 'Class Module' to add a new class module
to the project.
- Change these properties of the new class module:
Instancing: 2 - Creatable Multiuse
Name: TestClass
Public: True
- Add this single line of code to the General Declarations section of the
TestClass module:
Public MyVar As Integer
- Open the Options dialog by selecting Options from the Tools menu.
Switch to the Project tab, and change the 'Project Name:' text box from
'Project1' to 'Test1632'. This changes the first part of the ProgID to
'Test1632'.
- Choose 'Save Project' from the File menu to save the project files.
- Again from the File menu, select 'Make EXE File' to compile (and
register) the 16-bit OLE server. This will create a key off of
HKEY_CLASSES_ROOT named 'Test1632.TestClass' and a corresponding
CLSID key beneath HKEY_CLASSES_ROOT\CLSID.
- Close the 16-bit version of Visual Basic and start the 32-bit version of
Visual Basic 4.0.
- Open the Registry Editor (REGEDIT on Windows 95 Windows, or REGEDT32 on
Windows NT). Starting from HKEY_CLASSES_ROOT, find the
'Test1632.TestClass' key. Expand this key and make note of the CLSID. If
you like, you can do a search on this CLSID and find the relevant
LocalServer key pointing to the filename selected in step 7 above.
- Select 'Open Project' from the file menu and open the project created
in steps 1-8.
- Choose 'Make EXE File' from the File menu, change the filename of the
executable so that we will have 16- and 32-bit versions of the same
server, and choose OK.
- Switch back to the Registry Editor and do a refresh. Find the
'Test1632.TestClass' ProgID again, expand it, and notice that the CLSID
is different than the one seen in step 7. Finding this new CLSID and
observing the keys beneath will show that a LocalServer key does not
exist but that a LocalServer32 key does.
Modification Type: | Major | Last Reviewed: | 12/9/2003 |
---|
Keywords: | kbprb kbRegistry KB145676 |
---|
|