Component Naming and GUIDs
Gopalan Suresh Raj

Food for Thought...

import "unknwn.idl";

[uuid(6B8DEE50-E8C5-11d3-987F-006097A7D34F), dual]
interface IChecking : IDispatch {
  HRESULT create ([in] BSTR key, [in] BSTR name, [in] double startingBalance);
  HRESULT credit ([in] double amount, [in] BSTR key);
  HRESULT debit ([in] double amount, [in] BSTR key);
  HRESULT getBalance ([in] BSTR key, [out, retval] double* balance);
  HRESULT getCustomerName ([in] BSTR key, [out, retval] BSTR* name);
};
 
[uuid (6B8DEE51-E8C5-11d3-987F-006097A7D34F),  version (1.0)]
library Bank {
 importlib ("stdole32.tlb");

 [uuid(6B8DEE52-E8C5-11d3-987F-006097A7D34F)]
 coclass Checking {
  interface IChecking;
 };
}

                                     
                                                                         - Yours Truly

Dim checkingAccount As IChecking                                      'declare interface-based reference
Set checkingAccount = New Checking                                
  'use CoCreateInstance to load component
'invoke IChecking.create method
bool found = checkingAccount.create ("10001-101","Athul", 1000000.10)
checkingAccount.credit (450001.23, "10001-101")                 
'invoke IChecking.credit method
Dim balance = checkingAccount.getBalance ("10001-101"
'invoke IChecking.getBalance method
Set checkingAccount = Nothing                                              
'release reference to object
                                                                                                               - Yours Truly


In C++, Global Namespace Corruption happens when we place names in global scope and a collision occurs with the same names that are in use elsewhere within the system being compiled and linked as a single executable module.

In COM+, the global namespace is the aggregate of all possible computing devices in the world. Because your COM+ component may be remotely activated on any system in the world, it is important that the name given to the component implementation and interfaces are really unique across all possible execution environments.

Globally Unique Identifiers (GUID)
COM+ uses Globally Unique Identifiers (GUIDs) to name Interfaces and their Implementations. The concept of a GUID was originally conceived by the Open Software Foundation (OSF) for their Distributed Computing Environment (DCE). The GUID is a unique value in both space and time. It is generated on your development machine by a standard OSF DCE algorithm. It is this DCE algorithm that allows rapid development of COM+ objects without requiring use of namespace partitions. COM+ provides a tool called GUIDGEN that generates a unique GUID based on spacial and temporal information.

GUIDs are 16-byte extremely long integers. They are defined as a
struct in C/C++. The internal representation of a GUID is shown below:

 typdef struct _GUID {
  unsigned long Data1;
  unsigned short Data2;
  unsigned short Data3;
  unsigned char Data4 [8];
 } GUID;

Since this structure is large for an identifier, a datatype is defined in the standard headers that is used to pass GUIDs by value. These datatypes are defined as follows:

typdef const GUID& REFGUID;     // C++ typedef
typdef const GUID* REFGUID;     
// C++ typedef

GUIDs are used to eliminate name collisions across libraries. Each interface has a GUID called an Interface ID (IID). Each COM+ implementation has a unique GUID called the Class ID (CLSID). Both IID and CLSID are typedefs of GUID and are therefore type compatible with one another.

GUIDs are generated by a tool called GUIDGEN.EXE which is available in the Windows Platform SDK and is also bundled for convenience with development tools like Microsoft Visual Studio. Internally, GUIDGEN calls the COM+ API
CoCreateGUID() to generate a unique GUID. You can use the COM API to dynamically create GUIDs. It is defined as follows:

HRESULT CoCreateGuid (GUID *pGuid);

COM also provides functions for comparing GUIDs as follows:

BOOL IsEqualGuid (REFGUID refGuid1, REFGUID refGuid2);

Similarly, if you ever need to define a GUID in a C/C++ header file, use the DEFINE_GUID macro as follows:

DEFINE_GUID (CATID_MyCategory, 0x12345678, 0x1234, 0x1234, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08);

The algorithm used for generating the GUID is decentralized which means you can generate unique GUIDs from your local development machine.

The following code snippet shows how GUIDs can be generated programmatically using Java code in Visual J++.

public class GuidGen {
 public static void main(String[] args) {
  com.ms.com._Guid guid = com.ms.win32.Ole32.CoCreateGuid ();
  System.out.println(guid.toString());
 }
}

The following code snippet shows how GUIDs can be generated programmatically using Visual Basic.

Option Explicit
Private Type GUID
 Data1 As Long
 Data2 As Integer
 Data3 As Integer
 Data4(7) As Byte
End Type

Private Declare Function CoCreateGuid Lib "OLE32.DLL" (pGuid As GUID) As Long
Private Const S_OK = 0
' return value from CoCreateGuid

Function GetGUID() As String
 Dim lResult As Long
 Dim lguid As GUID
 Dim MyguidString As String
 Dim MyGuidString1 As String
 Dim MyGuidString2 As String
 Dim MyGuidString3 As String
 Dim DataLen As Integer
 Dim StringLen As Integer
 Dim i%

 On Error GoTo error_olemsg

 lResult = CoCreateGuid(lguid)

 If lResult = S_OK Then

  MyGuidString1 = Hex$(lguid.Data1)
  StringLen = Len(MyGuidString1)
  DataLen = Len(lguid.Data1)
 
'First 4 bytes (8 hex digits)
  MyGuidString1 = LeadingZeros(2 * DataLen, StringLen)  & MyGuidString1
 
  MyGuidString2 = Hex$(lguid.Data2)
  StringLen = Len(MyGuidString2)
  DataLen = Len(lguid.Data2)
 
'Next 2 bytes (4 hex digits)
  MyGuidString2 = LeadingZeros(2 * DataLen, StringLen) & Trim$(MyGuidString2)
 
  MyGuidString3 = Hex$(lguid.Data3)
  StringLen = Len(MyGuidString3)
  DataLen = Len(lguid.Data3)
  'Next 2 bytes (4 hex digits)
  MyGuidString3 = LeadingZeros(2 * DataLen, StringLen)  & Trim$(MyGuidString3)

  GetGUID = MyGuidString1 & MyGuidString2 & MyGuidString3

  For i% = 0 To 7
  MyguidString = MyguidString & Format$(Hex$(lguid.Data4(i%)), "00")
  Next i%

  'MyGuidString contains last 8 bytes of Guid (16 hex digits)
  GetGUID = GetGUID & MyguidString

 Else
  GetGUID = "00000000"
' return zeros if function unsuccessful
 End If

 Exit Function

error_olemsg:
 MsgBox "Error " & Str(Err) & ": " & Error$(Err)
 GetGUID = "00000000"
 Exit Function

End Function

Function LeadingZeros(ExpectedLen As Integer, ActualLen As Integer) As String
 LeadingZeros = String$(ExpectedLen - ActualLen, "0")
End Function

Private Sub Command1_Click()
 MsgBox GetGUID
End Sub

 

click here to go to
My Basic COM+ Tutorial...
click here to go to
My Advanced COM+/DNA Tutorial HomePage...

 

About the Author...
Gopalan Suresh Raj is a Software Architect, Developer and an active Author. He is contributing author to a couple of books "Enterprise Java Computing-Applications and Architecture" and "The Awesome Power of JavaBeans". His expertise spans enterprise component architectures and distributed object computing. Visit him at his Web Cornucopia© site (http://www.execpc.com/~gopalan) or mail him at gopalan@execpc.com.

 


Go to the Component Engineering Cornucopia page

This site was developed and is maintained by Gopalan Suresh Raj

This page has been visited times since March 13,1999.

Last Updated : Mar 14,'99

If you have any questions, comments, or problems regarding this site, please write to me I would love to hear from you.


Copyright (c) 1997-2000, Gopalan Suresh Raj - All rights reserved. Terms of use.

All products and companies mentioned at this site are trademarks of their respective owners.