Click here to Skip to main content
15,892,537 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
We have some legacy code (visual c++) that uses DCOM for client server connectivity. Under NT all works fine. We are now attempting to port this application to Windows 7 and are running into some issues.

We have set up test systems where both the server and client are Windows 7. If we log into the admin account on the client (which is an account on the server), all works fine. If we log into a test user account that does not exist on the server, our application does not work.

We have tried using CoInitializeSecurity to say "do not authorize" like this

C#
hr= CoInitializeSecurity(NULL,-1,NULL,NULL, RPC_C_AUTHN_LEVEL_NONE,
    RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);


but this fails. We also have tried specifying the user and password using SOLE_AUTHENTICATION_INFO but we are not a domain, so I am not sure what to put in for the domain information to tell it to ignore the domain (and our current attempt of using the server computer name for the domain fails too).

Is what we are attempting possible? We cannot create duplicate user accounts on the server - it is not allowed in our customer environment, so that is not an option. We can hard-code the user info into the application as an alternative, but I am not sure how to make that work.

I have added a note to this - we need to make the call to CoInitialzeSecurity with the authinfo filled in in VB6. Anyone have any examples of this?
Posted
Updated 5-Jun-12 4:38am
v2
Comments
Sergey Alexandrovich Kryukov 23-May-12 16:59pm    
Don't you think it's a good time to seize those childish DCOM games and get to TPC/IP? At least now you have an excuse for starting to do the real things. On higher level, WCF seems to be a good thing. Just a though...
--SA
Sergey Chepurin 24-May-12 4:31am    
This is still a huge number of COM clients communicating with COM servers via DCOM in Windows.
Sergey Alexandrovich Kryukov 28-May-12 18:58pm    
This maybe true but irrelevant. Why making one more? That time has gone, in my opinion. The whole idea of COM was a bridge between non-OOP OS APIs and OOP languages...
--SA
cotsjdixon 24-May-12 12:46pm    
What is different about DCOM in Windows 7 vs XP? This used to work without a problem in XP, but something is obviously different in Windows 7. I am sure I am not the only one out there who has had ths problem.

Does anyone know how to correctly set the security parameters or another way to correct this?
cotsjdixon 5-Jun-12 10:35am    
I think part of our problem is that we are missing the call to CoInitializeSecurity on the client side. I would like to specify the user/password in the authinfo structure, but I can't find example of how to do this in VB6 (old code, I know). All the examples I have found for VB6 just pass a 0 for the authinfo value, not a filled in structure.

I have discovered that our legacy client side application (in VB6) was not calling CoInitialzeSecurity. In XP this was fine. In Windows 7 the security is obviously tighter and we must now call this from our client. The next challenge was getting the VB6 code to work.

Here is the code that has made this work. I have trimmed out the bits that apply specifically to our application, but this code is what gets it going. Most of this has been copied from other web pages, but since I could not find a call to CoInitializeSecurity and all the associated code that goes with it, I am posting the consolidated code here.

VB
' Authentication service provider constants
' the default should be used.
Private Const RPC_C_AUTHN_NONE                  As Long = 0
Private Const RPC_C_AUTHN_GSS_NEGOTIATE         As Long = 9
Private Const RPC_C_AUTHN_GSS_KERBEROS          As Long = 10
Private Const RPC_C_AUTHN_WINNT                 As Long = &HA
Private Const RPC_C_AUTHN_DEFAULT               As Long = &HFFFFFFFF

' Authentication level constants
Private Const RPC_C_AUTHN_LEVEL_DEFAULT         As Long = 0
Private Const RPC_C_AUTHN_LEVEL_NONE            As Long = 1
Private Const RPC_C_AUTHN_LEVEL_CONNECT         As Long = 2
Private Const RPC_C_AUTHN_LEVEL_CALL            As Long = 3
Private Const RPC_C_AUTHN_LEVEL_PKT             As Long = 4
Private Const RPC_C_AUTHN_LEVEL_PKT_INTEGRITY   As Long = 5
Private Const RPC_C_AUTHN_LEVEL_PKT_PRIVACY     As Long = 6

Private Const RPC_C_AUTHZ_NONE = 0

' Impersonation level constants
Private Const RPC_C_IMP_LEVEL_ANONYMOUS         As Long = 1
Private Const RPC_C_IMP_LEVEL_IDENTIFY          As Long = 2
Private Const RPC_C_IMP_LEVEL_IMPERSONATE       As Long = 3
Private Const RPC_C_IMP_LEVEL_DELEGATE          As Long = 4

' Constants for the capabilities
Private Const API_NULL                          As Long = 0
Private Const S_OK                              As Long = 0
Private Const EOAC_NONE                         As Long = &H0
Private Const EOAC_MUTUAL_AUTH                  As Long = &H1
Private Const EOAC_CLOAKING                     As Long = &H10
Private Const EOAC_SECURE_REFS                  As Long = &H2
Private Const EOAC_ACCESS_CONTROL               As Long = &H4
Private Const EOAC_APPID                        As Long = &H8

Private Const SEC_WINNT_AUTH_IDENTITY_ANSI = &H1
Private Const SEC_WINNT_AUTH_IDENTITY_UNICODE = &H2

    Private Type COAUTHINFO
        dwAuthnSvc As Long
        dwAuthzSvc As Long
        pAuthIdentityData As Long '// Pointer to COAUTHIDENTITY
    End Type
    
    Private Type COAUTHLIST
        dwAuthList As Long
        pAuthList As Long '// Pointer to COAUTHINFO
    End Type
    
    Type COAUTHIDENTITY
        User As String
        UserLength As Long
        Domain As String
        DomainLength As Long
        Password As String
        PasswordLength As Long
        Flags As Long
    End Type



' Function Declaration
Private Declare Function CoInitializeSecurity Lib "OLE32.DLL" ( _
pSD As Any, _
ByVal cAuthSvc As Long, _
asAuthSvc As Long, _
pReserved1 As Any, _
ByVal dwAuthnLevel As Long, _
ByVal dwImpLevel As Long, _
ByVal pAuthInfo As Long, _
ByVal dwCapabilities As Long, _
pvReserved2 As Any _
) As Long

    Private Declare Sub CopyMemory Lib "kernel32" _
    Alias "RtlMoveMemory" (Destination As Any, _
    Source As Any, ByVal Length As Long)
    
    Private Declare Function GetProcessHeap Lib "kernel32" () As Long

    Private Declare Function HeapAlloc Lib "kernel32" _
    (ByVal hHeap As Long, ByVal dwFlags As Long, ByVal dwBytes As Long) As Long
    
    Private Declare Function HeapFree Lib "kernel32" _
    (ByVal hHeap As Long, ByVal dwFlags As Long, lpMem As Any) As Long
    
    Private Declare Sub CopyMemoryWrite Lib "kernel32" Alias _
    "RtlMoveMemory" (ByVal Destination As Long, _
    Source As Any, ByVal Length As Long)
    
    Private Declare Sub CopyMemoryRead Lib "kernel32" Alias _
    "RtlMoveMemory" (Destination As Any, _
    ByVal Source As Long, ByVal Length As Long)

Sub Main()
    Dim AuthInfo        As COAUTHINFO
    Dim AuthIdentity    As COAUTHIDENTITY
    Dim AuthList        As COAUTHLIST
    Dim hr              As Long
    Dim Context         As Long
    Dim pAuthIdentity   As Long
    Dim pAuthInfo       As Long
    Dim pAuthList       As Long
    Dim hHeap           As Long
    Dim strUser As String
    Dim strPassword As String
    Dim strDomain As String


    Dim lngHr As Long
    Dim lngAuthn As Long
    
  '// Get the process heap
    hHeap = GetProcessHeap()
    
    strUser = StrConv("UserName", vbUnicode)
    strPassword = StrConv("Password", vbUnicode)
    strDomain = ""
       
    With AuthIdentity
        .User = strUser
        .UserLength = LenB(strUser)
        .Password = strPassword
        .PasswordLength = LenB(strPassword)
        .Domain = strDomain
        .DomainLength = LenB(strDomain)
        .Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE
    End With
    
'// Allocate memory space for the pointer to the AuthIdentity Structure
    pAuthIdentity = HeapAlloc(hHeap, _
                              0, _
                              Len(AuthIdentity))

'// Get pointer to the memory block we just allocated
    CopyMemoryWrite pAuthIdentity, _
                    AuthIdentity, _
                    Len(AuthIdentity)
   
'// Get authority info for passing to server
    With AuthInfo
        .dwAuthnSvc = RPC_C_AUTHN_GSS_KERBEROS
        .dwAuthzSvc = RPC_C_AUTHZ_NONE
        .pAuthIdentityData = pAuthIdentity
    End With
    
'// Get a pointer to the AuthInfo Structure
    pAuthInfo = HeapAlloc(hHeap, _
                          0, _
                          Len(AuthInfo))
                          
    CopyMemoryWrite pAuthInfo, _
                    AuthInfo, _
                    Len(AuthInfo)
                    
'// Get authority list for passing to server
    With AuthList
        .dwAuthList = 1
        .pAuthList = pAuthInfo
    End With
    
'// Get a pointer to the AuthList Structure
    pAuthList = HeapAlloc(hHeap, _
                          0, _
                          Len(AuthList))
                          
    CopyMemoryWrite pAuthList, _
                    AuthList, _
                    Len(AuthList)

    lngAuthn = RPC_C_AUTHN_DEFAULT
    lngHr = CoInitializeSecurity(ByVal API_NULL, -1, _
        ByVal API_NULL, ByVal API_NULL, _
        RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IMPERSONATE, _
        pAuthList, EOAC_NONE, ByVal API_NULL)
    If (S_OK <> lngHr) Then
        MsgBox "CoInitializeSecurity failed with error code: 0x" _
        & Trim$(str$(Hex(lngHr))), vbCritical, _
        "Application Initialization Failure"
        Exit Sub
    End If
Exit Sub
 
Share this answer
 
There is a PDF manual from Siemens Description of the DCOM
Settings
[^]. It is for COM OPC client-server communication on XP. Try to follow the procedure described in this manual, which, i guess, is still not much different for Windows 7 computers.
Certainly your attempt with "CoInitializeSecurity to say "do not authorize"" was wrong.
 
Share this answer
 
Comments
cotsjdixon 24-May-12 7:08am    
I guess my terminology of "do not authorize" was not correct - I meant "no authorization" so any user would work. Which, of course, does not work.

The manual you mention says that for workgroups all users must have the same permissions on both server and client. It then says "If both computers are in one and the same domain, user administration is much simpler. The permissions for individual access are then verified over the domain server."

This is where my problem lies. We do not have a domain. We also cannot have duplicate users on the client and server.

Is there no way to get this to work? If I use the SOLE_AUTHENTICATION_INFO, can I just leave the domain out?
Sergey Chepurin 24-May-12 7:51am    
I thought so, but was afraid to get you wrong. From my DCOM experience limited to above mentioned COM OPC client-server communication i understand that either you follow the procedure described and get objects connected, or you simply fail. There are strict security settings of DCOM that exist on purpose to make it impossible for anyone to use "no authorization" approach in not trusted environment.
cotsjdixon 24-May-12 10:05am    
So I guess my original question still stands - how do I get CoInitializeSecurity (or DCOM) to work when there is no domain and I have a client user that is not a user on the server?
Sergey Chepurin 24-May-12 10:31am    
Yes, and i think it is not possible with DCOM. But you could prove me wrong.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900