2012-06-11 183 views
0

我目前正在研究一個需要從另一個系統上運行的COM對象檢索數據的MFC應用程序。當兩個系統都運行Windows XP並使用相同的手動設置用戶帳戶時(即在兩個系統上都有相同的用戶名和密碼,沒有域),我們已經擁有了相同的數據交換機制,並且完全支持這種機制。問題是我試圖設置它,這樣我就可以從另一臺具有相同用戶帳戶設置的計算機訪問同一個DCOM系統,但是使用公司域用戶帳戶登錄。如何正確使用COAUTHIDENTITY模擬CoCreateInstanceEx中的其他用戶?

現在,如果我使用運行方式手動運行我的應用程序並指定替代用戶,它會生效,但我正在尋找更好的解決方案。當我在CoCreateInstanceEx中爲COSERVERINFO設置COAUTHIDENTITY時,我指定了備用帳戶的用戶名和密碼,但似乎不起作用。我嘗試了域項中的各種東西 - 遠程計算機的本地計算機的計算機名稱,並將其留空 - 但似乎沒有任何幫助。

我試圖編輯服務器計算機上的對象的DCOM權限,以允許完全訪問Everyone帳戶,但這似乎沒有幫助,並且我一直無法找到任何有關什麼是有意義的錯誤消息真的錯了。如果我可以在服務器計算機上獲得某種日誌消息,以便準確地查看使用運行方式運行它時遇到的憑據,可能會有所幫助。有人有任何想法嗎?或者,也許知道當你從非域帳戶建立DCOM連接時,系統使用域名(有幾件事暗示計算機名稱已被使用,但在我嘗試時不起作用)。

代碼如下:

COAUTHINFO  AuthInfo; 
COAUTHIDENTITY AuthIdentity; 
COSERVERINFO ServerInfo; 
MULTI_QI  Results;  

AuthIdentity.Domain    = (unsigned short *) w_domain; 
AuthIdentity.DomainLength  = wcslen(w_domain); 
AuthIdentity.Flags    = SEC_WINNT_AUTH_IDENTITY_UNICODE; 
AuthIdentity.Password   = (unsigned short *) w_password; 
AuthIdentity.PasswordLength  = wcslen(w_password); 
AuthIdentity.User    = (unsigned short *) w_username; 
AuthIdentity.UserLength   = wcslen(w_username); 

AuthInfo.dwAuthnLevel   = RPC_C_AUTHN_LEVEL_CALL; 
AuthInfo.dwAuthnSvc    = RPC_C_AUTHN_WINNT; 
AuthInfo.dwAuthzSvc    = RPC_C_AUTHZ_NONE; 
AuthInfo.dwCapabilities   = EOAC_NONE; 
AuthInfo.dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE; 
AuthInfo.pAuthIdentityData  = &AuthIdentity; 
AuthInfo.pwszServerPrincName = NULL; 

ServerInfo.dwReserved1 = 0; 
ServerInfo.dwReserved2 = 0; 
ServerInfo.pAuthInfo = &AuthInfo; 
ServerInfo.pwszName  = w_nodename; 

Results.pIID = &_uuidof(_DS_SessionContext); 
Results.pItf = NULL; 
Results.hr = 0; 

hr = CoCreateInstanceEx(clsid, NULL, CLSCTX_ALL, &ServerInfo, (ULONG) 1, &Results);        
if(FAILED(hr)) 
{ 
    m_Error.Format("(0x%x) CoCreateInstanceEx for _DS_DataFrame failed.",hr); 
    m_Error2.Format("Make sure computer IP address is correct and connected."); 
    CoUninitialize(); 
    UpdateData(false); 
    UpdateWindow(); 
    return false;   
} 

pSession = (_DS_SessionContext *)Results.pItf; 

hr = pSession->raw_DS_GetVersion(&DSStatus, &version); 
if(FAILED(hr)) 
{ 
    m_Error.Format("(0x%x)GetVersion",hr); 
    CoUninitialize(); 
    UpdateData(false); 
    UpdateWindow(); 
    return false;   
} 

回答

0

啊,我想通了。原來,在DCOM中,創建實例和調用它的函數不會自動使用相同的安全區域。傳遞給CoCreateInstanceEx的COSERVERINFO中的認證信息僅適用於創建實例,並且稍後在該實例上調用函數時,它會失敗,因爲我使用應用程序的憑據調用這些函數。

爲了做正確,對實例調用函數之前,我必須(省略錯誤處理的清晰度)第一次調用:

hr = CoSetProxyBlanket(Results.pItf, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, 
    RPC_C_IMP_LEVEL_IMPERSONATE, &AuthIdentity, EOAC_NONE); 

此設置用於實例調用同一個安全毯是被用來創建它,因此一切正常。

相關問題