2

我目前正在开发一个 MFC 应用程序,该应用程序需要从另一个系统上运行的 COM 对象中检索数据。当两个系统都运行 Windows XP 并且手动设置相同的用户帐户(即两个系统上相同的用户名和密码,没有域)时,我们已经拥有相同的数据交换机制并得到完全支持。问题是我正在尝试对其进行设置,以便我可以从另一台设置了相同用户帐户但在公司域用户帐户下登录的计算机访问同一个 DCOM 系统。

现在,如果我使用 Run As 手动运行我的应用程序并指定备用用户,它就可以工作,但我正在寻找更好的解决方案。当我在 CoCreateInstanceEx 中为 COSERVERINFO 设置 COAUTHIDENTITY 时,我指定了备用帐户的用户名和密码,但这似乎不起作用。我在域条目中尝试了各种方法——本地计算机的计算机名称、远程计算机的计算机名称,并将其留空——但似乎没有任何帮助。

我尝试在服务器计算机上编辑对象的 DCOM 权限以允许对所有人帐户的完全访问,但这似乎没有帮助,而且我无法找到任何有意义的错误消息来说明真正的错误。如果我可以在服务器计算机上获得某种日志消息以确切了解使用 Run As 运行它时遇到的凭据,这可能会有所帮助。有人有什么想法吗?或者,当您从非域帐户建立 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;           
}
4

1 回答 1

2

啊,我想通了。事实证明,在 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);

这会将用于调用实例的安全毯设置为与创建实例相同的安全毯,因此一切正常。

于 2012-06-11T22:55:08.790 回答