我目前正在开发一个MFC应用程序,它需要从另一个系统上运行的COM对象中检索数据。当两个系统都运行Windows XP并且手动设置相同的用户帐户(即两个系统上都有相同的用户名和密码,没有域)时,我们已经有了相同的数据交换机制,并且完全支持。麻烦的是,我正在设置它,以便我可以从另一台具有相同用户帐户设置的计算机访问同一个DCOM系统,但是在公司域用户帐户下登录。
现在,如果我使用运行方式手动运行我的应用程序并指定备用用户,它可以工作,但我正在寻找更好的解决方案。当我在CoCreateInstanceEx中为COSERVERINFO设置COAUTHIDENTITY时,我指定备用帐户的用户名和密码,这似乎不起作用。我在域名条目中尝试了各种各样的东西 - 本地计算机的计算机名称,远程计算机的计算机名称,并将其留空 - 但似乎没有任何帮助。
我尝试编辑服务器计算机上对象的DCOM权限,以允许完全访问Everyone帐户,但这似乎没有帮助,而且我无法找到任何有意义的错误消息错误。如果我可以在服务器计算机上获得某种日志消息,以便在使用“运行方式”运行它时确切地查看所发生的凭据,这可能会有所帮助。有人有什么想法吗?或者,当您从非域帐户进行DCOM连接时,可能知道系统使用Domain的内容(有些事情意味着使用了计算机名称,但是当我尝试使用时这不起作用)。
代码如下:
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 :(得分:0)
为了正确地做到这一点,在调用实例上的函数之前,我必须先调用(为清楚起见省略了错误处理):
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);
这将用于调用实例的安全毯设置为用于创建实例的安全毯,因此一切正常。