- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
问题:
我在代理上成功调用了 CoSetProxyBlanket(如果这是正确的术语),然后我在同一个代理上调用了 QueryInterface,但我收到了 0x80070005(“拒绝访问”)的结果。但是,如果我首先使用相同的凭据调用 CoInitializeSecurity (我试图避免这种情况),则调用会成功。
问题:
如何在不调用CoInitializeSecurity的情况下成功获取到自己需要的接口(interface)?据我了解,一个进程只能调用此方法一次,因此它与制作 dll 不兼容,通常可以用对 CoSetProxyBlanket 的调用来代替。
详细信息:
我正在尝试构建自己的 OPC 客户端,它可以与运行在不同域上的计算机通信,无需匹配的用户帐户。
首先,我创建一个身份结构,其中包含在服务器上有效的域、用户名和密码:
COAUTHINFO authInfo;
COAUTHIDENTITY authIdentity;
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.pAuthInfo = &authInfo;
然后我可以使用此服务器信息调用 CoCreateInstanceEx
并获取我的 OPC 服务器 (IID_IOPCServer
) 的句柄 (m_IOPCServer
)。
获得句柄后,我发现有必要通过此调用再次设置更多权限(参见 How does impersonation in DCOM work?):
hr = CoSetProxyBlanket(m_IOPCServer, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE,
NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE,
&authIdentity, EOAC_NONE);
在此之后,我能够成功获得 OPC 项组的句柄:
hr = m_IOPCServer->AddGroup(L"", FALSE, reqUptRate, clientHandle,
NULL, NULL, lcid, &m_hServerGroup, &revisedUptRate,
IID_IOPCItemMgt,(LPUNKNOWN*)&m_IOPCItemMgt);
但是,当我尝试使用这段代码时:
hr = m_IOPCItemMgt->QueryInterface(IID_IOPCSyncIO, (void**)&m_IOPCSyncIO);
结果是 0x80070005(“拒绝访问”)。即使我在 m_IOPCItemMgt 上成功调用 CoSetProxyBlanket 也是如此。但是,如果我首先调用 CoInitializeSecurity,则调用会成功。
我认为问题与 How does impersonation in DCOM work? 有关因为 QueryInterface 函数是一种对象创建形式,所以它不使用与其他方法调用(如 AddGroup)相同的安全性。但是在 Microsoft 引用中 QueryInterface ,在给实现者的注释下,听起来 QueryInterface 不应该检查 ACL,并且在返回值下,没有提到 Access Denied 是一种可能性。我不认为这个问题是特定于实现的,因为我已经在一些著名的商业 OPC 服务器(例如 Matrikon Simulation Server)以及没有实现任何额外安全性的开源 LightOPC 上尝试了我的代码。
我猜我需要做的是找到一种方法来复制这个命令
hr = m_IOPCItemMgt->QueryInterface(IID_IOPCSyncIO, (void**)&m_IOPCSyncIO);
但同时提供 authIdentity
。这可能吗?可以使用 CoCreateInstanceEx 或 CoGetClassObject 或其他一些 COM 调用来完成吗?
最佳答案
无需过多赘述:CoInitializeSecurity 总是在每个进程中至少调用一次。这可以隐式或显式地完成。如果您的代码没有进行显式调用,DCOM 运行时会使用从注册表填充的参数为您完成。您可以尝试调整适当的注册表值以强制 DCOm 使用与显式调用中使用的值相似的值。保存这些值的注册表项是“HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID{AppID_GUID}” 此处描述了此项:https://msdn.microsoft.com/en-us/library/windows/desktop/ms693736(v=vs.85).aspx
关于c++ - 使用自定义标识调用 QueryInterface,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39460079/
我有一个非托管 C++ 类,其中有一个 com 映射。例如: BEGIN_COM_MAP (MyClass) COM_INTERFACE_ENTRY(...) END_COM_MAP 但是现在如果
问题: 我在代理上成功调用了 CoSetProxyBlanket(如果这是正确的术语),然后我在同一个代理上调用了 QueryInterface,但我收到了 0x80070005(“拒绝访问”)的结果
如果我有 IUnknown *ptr , 我需要调用Release()在我通过ptr->QueryInterface()获得的每个界面上, 另外调用ptr->Release()当我完成 ptr ? 我
我试图找到这个问题的答案,但完全没有运气。没有关于如何使用 Marshal.QueryInterface 返回的值的文档。 (在我的情况下是“pISomething”)。它是 IntPtr 的一个实例
考虑以下代码: TMyList = class(TList, IMyList) Delphi 向我显示错误: [DCC Error] test.pas(104): E2003 Undeclared i
我写了这段代码 'use strict'; module.exports = { up: (queryInterface, Sequelize) => { }, down: (queryI
假设我有一个实现两个或多个 COM 接口(interface)的类(与 here 完全一样): class CMyClass : public IInterface1, public IInterfa
IUnknown::QueryInterface() 被传递了一个 void** 参数,表示放置检索到的接口(interface)的地址。 STDMETHOD QueryInterface(/* [i
我想将此 USB 检测器转换为 Swift 3 https://gist.github.com/zachbadgett/471d72e83fee413d0f38 但是我卡在了这条线上: let dev
我正在尝试使用 Word 文档中的一些嵌入对象。较早的张贴者告诉我,这不是直截了当的。以下是链接答案的摘录: "As I mentioned earlier, utilizing the embedd
queryInterface.removeConstraint() 的文档没有记录可以传递给 removeConstraint() 方法的 options 对象。事实上,没有记录可以传递给各种 que
我在实用程序库中遇到问题,它执行一些 COM 互操作。它保留对在调用之间使用的 COM 对象的引用。 如果所有方法都是从使用相同 COM 线程模型的线程调用的,则该类可以正常工作。 但是,如果创建 C
是否可以为使用 ATL 的类提供 QueryInterface 的实现? BEGIN_COM_MAP(CConcrete) // Defines _InternalQueryInterface C
在我的应用程序中,我通过 CreateInstance 创建了一个对象 A,该对象又创建了一个对象 B。这两个对象应该存在于同一个进程中。 现在我看到对象 B 在请求某个接口(interface)时返
以上是否可行? 我可以这样做吗: IUnknown *punk; punk->QueryInterface(IID_MyInterface, (void**)&m_pMyInterface); 我认为
我正在尝试在现有 COM 组件中构建连接点。我从 CCmdTarget 派生类,并按照 MSDN 中的描述在类声明和实现中调用 MFC 宏。组件已正确构建、链接和运行。但是,当我调试我的客户端应用程序
这个问题在这里已经有了答案: Handling CoCreateInstance return value (2 个答案) 关闭 8 年前。 设想一种情况: CComPtr pGraph; HRES
我想知道是否有更简洁的方法来编写下面的(工作)代码: uint uEnum = 0; PStore.EnumTypes(0, 0, ref uEnum); System.Reflection.Memb
IUnknown::QueryInterface() 的典型实现方式如下:为每个支持的接口(interface) ID 使用一个 if-else-if 链并执行以下操作: if( iid == __u
我明白 QueryInterface 是什么方法实际上是这样做的——它只返回一个指向特定接口(interface)的指针。但我的问题是,我为什么要使用这种方法? 我的意思是,有什么区别 QueryIn
我是一名优秀的程序员,十分优秀!