2012-06-11 12 views
0

В настоящее время я работаю над приложением MFC, которое должно извлекать данные из COM-объекта, запущенного в другой системе. У нас уже есть тот же механизм обмена данными, который работает и полностью поддерживается, когда обе системы работают под управлением Windows XP и одинаково настраивают учетную запись пользователя (то же имя пользователя и пароль для обеих систем, ни для домена). Проблема в том, что я пытаюсь настроить его таким образом, что я могу получить доступ к этой же системе DCOM с другого компьютера, который имеет ту же настройку учетной записи пользователя, но входит в систему под учетной записью пользователя корпоративного домена.Как правильно выдать себя за другого пользователя в CoCreateInstanceEx с помощью COAUTHIDENTITY?

Прямо сейчас, это работает, если я вручную запускаю свое приложение с помощью Run As и указываю альтернативного пользователя, но я ищу лучшее решение. Когда я устанавливаю COAUTHIDENTITY для COSERVERINFO в CoCreateInstanceEx, я указываю имя пользователя и пароль для альтернативной учетной записи, и это не работает. Я пробовал разные вещи в записи «Домен» - имя компьютера на локальном компьютере, удаленном компьютере и оставил его пустым, но никто, похоже, не помогает.

Я пробовал редактировать разрешения DCOM для объекта на серверном компьютере, чтобы разрешить полный доступ к учетной записи Everyone, но это, похоже, не помогает, и я не смог найти никаких значимых сообщений об ошибках в отношении того, что действительно неправильно. Вероятно, это помогло бы, если бы я мог получить какое-то сообщение журнала на компьютер-сервере, чтобы точно узнать, какие учетные данные возникают, когда я запускаю его с помощью 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;   
} 

ответ

0

Ах, я понял это. Оказывается, что в DCOM создание на нем экземпляров и вызывающих функций автоматически не использует одно и то же защитное одеяло. Информация об аутентификации в COSERVERINFO, передаваемая CoCreateInstanceEx, применяется только к созданию экземпляра, а когда я вызываю функции на этом экземпляре позже, это терпит неудачу, потому что я вызываю эти функции, используя учетные данные приложения.

Чтобы сделать это правильно, перед вызовом функции на экземпляре, я должен первый вызов (обработка ошибок опущена для ясности):

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); 

Устанавливает одеяло безопасности, используемое для вызова экземпляра тех же самое, что был использован для его создания, и, следовательно, все работает.