c - 无法在 Windows 7 上创建高程 COM 对象

标签 c com windows-7 uac moniker

我正在用 C 语言开发一个 COM 代理 对象,我的应用程序将使用它来调用 UAC 提升对话框以执行某些需要管理权限的操作。

计划是让它导出一个函数,该函数接受一个指向具有可变数量参数的函数的指针,并在不同的上下文中执行它。这样,应用程序可以使用此对象执行一些具有管理员权限的操作,他们需要做的就是使用该对象并将指针传递给必须以所述权限执行的函数。

这部分工作,调用 CoCreateInstance 正常,传递函数指针并执行我的函数。

但是,当我使用 COM Elevation Moniker archive 和 Microsoft 的 CoCreateInstanceAsAdmin 示例代码创建此对象的实例时,出现了问题。

代码如下:

HRESULT CoCreateInstanceAsAdmin(HWND hwnd, REFCLSID rclsid, REFIID riid, __out void ** ppv)
{
 // Manual implementation of CreateInstanceAsAdmin
 CComPtr<IBindCtx> BindCtx;
 HRESULT hr = CreateBindCtx(0,&BindCtx);
 BIND_OPTS3 bo;
 memset(&bo, 0, sizeof(bo));
 bo.cbStruct = sizeof(bo);
 bo.grfMode = STGM_READWRITE;
 bo.hwnd = hwnd;
 bo.dwClassContext = CLSCTX_LOCAL_SERVER;
 hr = BindCtx->SetBindOptions(&bo);
 if (SUCCEEDED(hr))
 {
  // Use the passed in CLSID to help create the COM elevation moniker string
  CComPtr<IMoniker> Moniker;
  WCHAR wszCLSID[50];
  WCHAR wszMonikerName[300];
  StringFromGUID2(rclsid,wszCLSID,sizeof(wszCLSID) / sizeof(wszCLSID[0]));
  //Elevation:Administrator!new
  hr = StringCchPrintfW(wszMonikerName, sizeof(wszMonikerName)/sizeof(wszMonikerName[0]), L"Elevation:Administrator!new:%s", wszCLSID);
  if (SUCCEEDED(hr))
  {
   // Create the COM elevation moniker
   ULONG ulEaten = 0;
   ULONG ulLen = (ULONG)wcslen(wszMonikerName);
   LPBC pBindCtx = BindCtx.p;
   hr = MkParseDisplayName(pBindCtx,wszMonikerName,&ulEaten,&Moniker);
   if (SUCCEEDED(hr) && ulEaten == ulLen)
   {
    // Use passed in reference to IID to bind to the object
    IDispatch * pv = NULL;
    hr = Moniker->BindToObject(pBindCtx,NULL,riid,ppv);
   }
  }
 }
 return hr;
}

调用 CoCreateInstanceAsAdmin 失败并显示“类未注册”。

通过创建以下注册表项(这里是 REG 文件的主体)注册对象


[HKEY_CLASSES_ROOT\COMsurrogate]
@="COMsurrogate Class"

[HKEY_CLASSES_ROOT\COMsurrogate\CurVer]
@="COMsurrogate.1"

[HKEY_CLASSES_ROOT\COMsurrogate\CLSID]
@="{686B6F70-06AE-4dfd-8C26-4564684D9F9F}"

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}]
@="COMsurrogate Class"
"LocalizedString"="@C:\\Windows\\system32\\COMsurrogate.dll,-101"
"DllSurrogate"=""

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}\ProgID]
@="COMsurrogate.1"

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}\VersionIndependentProgID]
@="COMsurrogate"

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}\InprocServer32]
@="@C:\\windows\system32\COMsurrogate.dll"
"ThreadingModel"="Apartment"

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}\NotInsertable]

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}\Programmable]

我想某些注册表项丢失了 - 这是我在阅读错误消息时得出的结论。但是,此注册表项列表是在浏览 MSDN 和其他站点上的文档后编译的 - 因此我非常确定没有遗漏任何内容。

在我试图解决的问题中,有一个是通过 ATL 实现它(以便自动注册)。这行得通,但问题是我无法将函数指针传递给 MIDL 生成的函数原型(prototype)。

我尝试使用 VARIANT 类型传递它:


 v.vt = VT_PTR;
 void (*myptr)(void);
 myptr = &DoTheStuff;
 v.byref = myptr;
 hr = theElevated->CoTaskExecuter(0, v);

结果我得到“无效的参数类型”。

有人可以阐明这个主题吗?或许我试图实现的目标在设计上是不可能的?

最佳答案

我相信您遇到的问题是设计使然,并且窗口安全改进的目的是帮助避免潜在的安全风险。

关于c - 无法在 Windows 7 上创建高程 COM 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4144967/

相关文章:

c - 写入和打印两个字符串交替组合时出现段错误?

.net - 处理的 TreeView.SelectedItemChanged 事件仍然冒泡

windows-7 - 批量/CMD move 不适用于文件夹

android - 如何增加 AVD(android 虚拟设备)的 RAM?

c - C 中的退出函数

c++ - Windows——在子进程中继承控制台文件句柄

c++ - 如何在 UML 事件图中表示编译时条件?

c# - 使 C# 类库在 Visual Studio 2022 中 COM 可见

c++ - 当使用 CreateObject 从 VBScript 通过 COM 引用 C++ DLL 时,如何处理 DLL 版本?

java - 在 Java Swing 中更改面板标题的颜色