KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q145676: PRB: Registry Overwritten with Same ProgID/Different Bitness Ser

Article: Q145676
Product(s): Microsoft Visual Basic for Windows
Version(s): WINDOWS:4.0
Operating System(s): 
Keyword(s): kbRegistry kbVBp kbVBp400 kbGrpDSVB kbDSupport
Last Modified: 11-JAN-2001

-------------------------------------------------------------------------------
The information in this article applies to:

- Microsoft Visual Basic Standard Edition, 32-bit, for Windows, version 4.0 
- Microsoft Visual Basic Professional Edition, 16-bit, for Windows, version 4.0 
- Microsoft Visual Basic Professional Edition, 32-bit, for Windows, version 4.0 
- Microsoft Visual Basic Enterprise Edition, 16-bit, for Windows, version 4.0 
- Microsoft Visual Basic Enterprise Edition, 32-bit, for Windows, version 4.0 
-------------------------------------------------------------------------------

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
------------------

1. Start Visual Basic 4.0, 16-bit. Form1 is created by default.

2. From the Insert menu, choose 'Class Module' to add a new class module to the
  project.

3. Change these properties of the new class module:

  Instancing:      2 - Creatable Multiuse
  Name:         TestClass
  Public:         True

4. Add this single line of code to the General Declarations section of the
  TestClass module:

     Public MyVar As Integer

5. 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'.

6. Choose 'Save Project' from the File menu to save the project files.

7. 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.

8. Close the 16-bit version of Visual Basic and start the 32-bit version of
  Visual Basic 4.0.

9. 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.

10. Select 'Open Project' from the file menu and open the project created in
  steps 1-8.

11. 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.

12. 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.

Additional query words:

======================================================================
Keywords          : kbRegistry kbVBp kbVBp400 kbGrpDSVB kbDSupport 
Technology        : kbVBSearch kbAudDeveloper kbVB400Search kbVB400 kbVB16bitSearch
Version           : WINDOWS:4.0
Issue type        : kbprb

=============================================================================

THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Copyright Microsoft Corporation 1986-2002.