2

私は現在、別のシステムで実行されている COM オブジェクトからデータを取得する必要がある MFC アプリケーションに取り組んでいます。両方のシステムが Windows XP を実行し、同じユーザー アカウントを手動でセットアップした場合 (つまり、両方のシステムで同じユーザー名とパスワード、ドメインなし)、この同じデータ交換メカニズムが既に機能し、完全にサポートされています。問題は、同じユーザー アカウントが設定されているが、企業ドメイン ユーザー アカウントでログインしている別のコンピューターから、この同じ DCOM システムにアクセスできるように設定しようとしていることです。

現在、Run As を使用してアプリケーションを手動で実行し、代替ユーザーを指定すると機能しますが、より良い解決策を探しています。CoCreateInstanceEx で COSERVERINFO の COAUTHIDENTITY を設定するときに、代替アカウントのユーザー名とパスワードを指定しましたが、うまくいかないようです。ドメイン エントリで、ローカル コンピューターのコンピューター名、リモート コンピューターのコンピューター名、空白のままにするなど、さまざまなことを試しましたが、何も解決しないようです。

サーバー コンピューター上のオブジェクトの 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;           
}
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 に答える