Microsoft KB Archive/268884

From BetaArchive Wiki
Knowledge Base


How To Set or Retrieve the Authentication Level of a DCOM Client

Article ID: 268884

Article Last Modified on 8/30/2004



APPLIES TO

  • Microsoft Visual Basic 6.0 Professional Edition
  • Microsoft Visual Basic 6.0 Enterprise Edition



This article was previously published under Q268884

SUMMARY

If you need to set a custom value for the Authentication Level for a DCOM client application, you can use one of the following options:

  • Call CoInitializeSecurity.
  • Create an AppId in the registry that has a double word (DWORD) value set for AuthenticationLevel and map this AppId to the executable file name of your DCOM client.

This article uses the second option.

MORE INFORMATION

DCOM security settings are process-specific. If you do not set the AuthenticationLevel of the client's process, then the default AuthenticationLevel is used. Because you do not use CoInitilizeSecurity from your client to set the AuthenticationLevel and your client executable is not included in the Dcomcnfg utility, you must create your own registry mapping in order to set the client's authentication level either programmatically or by using Regedit.

Do the mapping in the registry by starting under:

HKEY_CLASSES_ROOT\AppId\


and then adding a key with the name of your client's executable name (myclient.exe). In this key there should be a string value, AppId, with your generated GUID. You also need to have a key under:

HKEY_CLASSES_ROOT\AppId\


with your generated GUID. In this key there should be a DWORD value, AuthenticationLevel, which is set to the value of the authentication level you want the client to use. This completes the registry mapping for the client's executable.

Assuming that your client executable is named myclient.exe, the mapping should look like the following in the registry.

Key Value
HKCR\AppId\myclient.exe     (Default)                      REG_SZ              (value not set)
     AppId                           REG_SZ              {GUID}
HKCR\AppId\{GUID}    (Default)                       REG_SZ              (value not set)
     AuthenticationLevel        REG_DWORD       0x00000001


The following is sample code for an application that creates the preceding registry entries for a given executable:

  1. Start a Standard EXE Project in Visual Basic. Form1 is created by default.
  2. Add two TextBox, two Label, and two CommandButton controls to the form.
  3. Add the following code to the form:

    Private Sub Command1_Click()
        If Text1 = "" Or Val(Text2) < 1 Or Val(Text2) > 6 Then Exit Sub
        SetAuthentication Val(Text2), Text1
    End Sub
    
    Private Sub Command2_Click()
        Dim auth As Integer
        auth = GetAuthenticationLevel(Text1)
        MsgBox "The Authentication Level for: " & Text1 & " is " & auth
    End Sub
    
    Private Sub Form_Load()
        With Me
            .Width = 3225
            .Height = 1950
            .Caption = "Set DCOM Client Authentication Level"
        End With
        With Command1
            .Height = 615
            .Width = 1450
            .Left = 1650
            .Top = 120
            .Caption = "Set Authentication Level"
            .TabIndex = 2
        End With
        With Command2
            .Height = 615
            .Width = 1450
            .Left = 1650
            .Top = 840
            .Caption = "Get Authentication Level"
            .TabIndex = 2
        End With
        With Text1
            .Text = ""
            .Height = 285
            .Left = 0
            .Top = 360
            .Width = 1455
            .TabIndex = 0
        End With
        With Text2
            .Text = ""
            .Height = 285
            .Left = 0
            .Top = 1200
            .Width = 255
            .TabIndex = 1
        End With
        With Label1
            .Caption = "Client EXE name"
            .Left = 0
            .Top = 0
        End With
        With Label2
            .Caption = "Authentication Level (1-6)"
            .Left = 0
            .Top = 720
        End With
    End Sub
                        
  4. On the Project menu, add a standard module to the project, and then paste the following code in the code module:

    Private Type GUID
        Data1 As Long
        Data2 As Integer
        Data3 As Integer
        Data4(7) As Byte
    End Type
    
    Private Const GUID_LENGTH As Long = 39
    
    Private Const REG_SZ As Long = 1
    Private Const REG_DWORD As Long = 4
    
    Private Const ERROR_SUCCESS = 0
    Private Const ERROR_NONE = 0
    
    Private Const HKEY_CLASSES_ROOT = &H80000000
    
    Private Const KEY_ALL_ACCESS = &H3F
    Private Const KEY_QUERY_VALUE = &H1
    
    Private Const REG_OPTION_NON_VOLATILE = 0
    
    Private Declare Function RegCloseKey Lib "advapi32.dll" _
    (ByVal hKey As Long) As Long
    
    Private Declare Function RegCreateKeyEx Lib "advapi32.dll" Alias _
    "RegCreateKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, _
    ByVal Reserved As Long, ByVal lpClass As String, ByVal dwOptions _
    As Long, ByVal samDesired As Long, ByVal lpSecurityAttributes _
    As Long, phkResult As Long, lpdwDisposition As Long) As Long
    
    Private Declare Function RegSetValueExString Lib "advapi32.dll" Alias _
    "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, _
    ByVal Reserved As Long, ByVal dwType As Long, ByVal lpValue As _
    String, ByVal cbData As Long) As Long
    
    Private Declare Function RegSetValueExLong Lib "advapi32.dll" Alias _
    "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, _
    ByVal Reserved As Long, ByVal dwType As Long, lpValue As Long, _
    ByVal cbData As Long) As Long
    
    Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias _
    "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, _
    ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) _
    As Long
    
    Private Declare Function RegQueryValue Lib "advapi32.dll" Alias _
    "RegQueryValueA" (ByVal hKey As Long, ByVal lpSubKey As String, _
    ByVal lpValue As String, lpcbValue As Long) As Long
    
    Private Declare Function RegQueryValueExString Lib "advapi32.dll" _
    Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, _
    ByVal lpReserved As Long, lpType As Long, ByVal lpData As String, _
    lpcbData As Long) As Long
    
    Private Declare Function RegQueryValueExLong Lib "advapi32.dll" Alias _
    "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As _
    String, ByVal lpReserved As Long, lpType As Long, lpData As _
    Long, lpcbData As Long) As Long
          
    Private Declare Function CoCreateGuid Lib "ole32.dll" (pGUID As GUID) _
    As Long
    
    Private Declare Function StringFromGUID2 Lib "ole32.dll" (pGUID As GUID, _
    ByVal PointerToString As Long, ByVal MaxLength As Long) As Long
    
    Public Function CreateGUID() As String
        Dim udtGUID As GUID
        Dim sGUID As String
        Dim lResult As Long
        If (CoCreateGuid(udtGUID) = 0) Then
            sGUID = String$(GUID_LENGTH, 0)
            lResult = StringFromGUID2(udtGUID, StrPtr(sGUID), GUID_LENGTH)
            CreateGUID = sGUID
        End If
    End Function
    
    Public Sub SetAuthentication(AuthLevel As Integer, ExeName As String)
        Dim hNewKey As Long
        Dim lRetVal As Long
        Dim sMyGUID As String
        Dim sNewKey As String
        Dim lpData As Long
        Dim lpcbData As Long
        
        lpData = CLng(AuthLevel)
        lpcbData = Len(lpData)
        sMyGUID = CreateGUID()
        sNewKey = "AppId\" & sMyGUID
        
        lRetVal = RegCreateKeyEx(HKEY_CLASSES_ROOT, sNewKey, 0&, _
           vbNullString, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0&, _
           hNewKey, lRetVal)
        lRetVal = RegSetValueExLong(hNewKey, "AuthenticationLevel", 0&, _
           REG_DWORD, lpData, lpcbData)
        RegCloseKey (hNewKey)
        
        sNewKey = "AppId\" & ExeName & ".exe"
        lRetVal = RegCreateKeyEx(HKEY_CLASSES_ROOT, sNewKey, 0&, _
           vbNullString, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0&, _
           hNewKey, lRetVal)
        lRetVal = RegSetValueExString(hNewKey, "AppId", 0&, REG_SZ, _
           sMyGUID, Len(sMyGUID))
        RegCloseKey (hNewKey)
        MsgBox sMyGUID
    End Sub
    
    Public Function GetAuthenticationLevel(ExeName As String) As Integer
        Dim hKey As Long
        Dim lRetVal As Long
        Dim sKeyName As String
        Dim lpData As String
        Dim lpdata2 As Long
        Dim lpcbData As Long
        Dim myappid As String
        Dim auth As Integer
        
        If ExeName = "" Then
            GetAuthenticationLevel = -1
            MsgBox "Invalid File Name"
            Exit Function
        End If
        
        lRetVal = RegOpenKeyEx(HKEY_CLASSES_ROOT, "AppId\" & ExeName, 0, _
           KEY_QUERY_VALUE, hKey)
        If lRetVal = ERROR_SUCCESS Then
            lpcbData = 40
            lpData = Space$(lpcbData)
            lRetVal = RegQueryValueExString(hKey, "AppId", 0&, REG_SZ, _
               lpData, lpcbData)
            If lRetVal = ERROR_NONE Then
                myappid = Left$(lpData, lpcbData - 1)
                RegCloseKey (hKey)
                sKeyName = "AppID\" & myappid & "\"
                lRetVal = RegOpenKeyEx(HKEY_CLASSES_ROOT, sKeyName, 0&, _
                KEY_ALL_ACCESS, hKey)
                If lRetVal = ERROR_SUCCESS Then
                    lpdata2 = CLng(0)
                    lpcbData = Len(lpdata2)
                    lRetVal = RegQueryValueExLong(hKey, _
                       "AuthenticationLevel", 0&, REG_DWORD, lpdata2, lpcbData)
                    If lRetVal = ERROR_NONE Then
                        auth = CInt(lpdata2)
                        GetAuthenticationLevel = auth
                    Else
                        MsgBox lRetVal & " - Unable to read authentication level."
                        GetAuthenticationLevel = -2
                    End If
                Else
                    MsgBox lRetVal & " - Cannot find AppID for " & sKeyName
                    GetAuthenticationLevel = -3
                End If
                RegCloseKey (hKey)
            Else
                 MsgBox lRetVal & " - Cannot read AppID value for " & sKeyName
                 GetAuthenticationLevel = -4
            End If
        Else
            MsgBox lRetVal & " - Cannot find exe name - " & sKeyName
            GetAuthenticationLevel = -5
        End If
    
    Exit Function
    QueryValueExExit:
        MsgBox lRetVal & " - Unexpected error"
        GetAuthenticationLevel = -7
        Exit Function
    QueryValueExError:
        Resume QueryValueExExit
    End Function
                        
  5. Run the project. Type the executable file name of the client application into Text1, and then type the authentication level you want to set into Text2.
  6. Click the Set Authentication Level CommandButton. The mapping is now created in the registry and the authentication level is set for the client executable. Click the Get Authentication Level CommandButton and note that a message box appears containing the authentication level you just set.


REFERENCES

For more information on AppId, see the following directory in MSDN:

\Platform SDK\Component Services\COM\COM Fundamentals\Reference\Registry Entries\AppId


For additional information on securing objects in code, click the article numbers below to view the articles in the Microsoft Knowledge Base:

239561 How To Use CoInitializeSecurity in Visual Basic


249636 How To Use the CoSetProxyBlanket Function in Visual Basic



Additional query words: myclient

Keywords: kbhowto kbregistry kbsecurity kbdcom kbclientserver KB268884