Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 你能在没有管理员的情况下注册directshow筛选器吗?_C++_Winapi_Com_Directshow - Fatal编程技术网

C++ 你能在没有管理员的情况下注册directshow筛选器吗?

C++ 你能在没有管理员的情况下注册directshow筛选器吗?,c++,winapi,com,directshow,C++,Winapi,Com,Directshow,我想注册一个虚拟directshow源设备而不需要管理员。在另一篇文章中,我看到有人提到,你可以通过HKEY_CURRENT_用户而不是HKEY_classes_ROOT或HKEY_LOCAL_机器注册每个用户帐户的COM类。这很有效,我可以通过HKEY_CURRENT_USER\Software\Classes注册该类,而无需UAC 要显示源代码/筛选器,我需要调用IFilterMapper2::RegisterFilter。如果没有UAC的特权,这将失败。(E_ACCESSDENIED常规访

我想注册一个虚拟directshow源设备而不需要管理员。在另一篇文章中,我看到有人提到,你可以通过HKEY_CURRENT_用户而不是HKEY_classes_ROOT或HKEY_LOCAL_机器注册每个用户帐户的COM类。这很有效,我可以通过HKEY_CURRENT_USER\Software\Classes注册该类,而无需UAC

要显示源代码/筛选器,我需要调用
IFilterMapper2::RegisterFilter
。如果没有UAC的特权,这将失败。(
E_ACCESSDENIED常规访问被拒绝错误。

微软并不清楚调用RegisterFilter的实际作用。我知道它在
HKEY\U CLASSES\U ROOT\CLSID\category CLSID\Instance\filter CLSID
下创建了一个注册表项,但其中一个键值是FilterData,它是一个二进制值,理论上应该与此结构匹配;但是数据没有完全对齐,所以他们也必须在其中写入其他数据


是否仍要在用户帐户级别注册筛选器?

注册信息位于
HKEY\U LOCAL\U MACHINE
下,因此您必须拥有本地管理员帐户和提升的权限才能进行注册。

首先您必须注册服务器:

STDAPI AMovieSetupRegisterServerOverride(CLSID clsServer, LPCWSTR szDescription, LPCWSTR szFileName, LPCWSTR szThreadingModel = L"Both", LPCWSTR szServerType = L"InprocServer32")
{
    TCHAR achTemp[MAX_PATH];

    OLECHAR szCLSID[CHARS_IN_GUID];
    HRESULT hr = StringFromGUID2(clsServer, szCLSID, CHARS_IN_GUID);

    HKEY hkey;
    DWORD d;
    wsprintf(achTemp, TEXT("Software\\Classes\\CLSID\\%ls"), szCLSID);
    LONG lreturn = RegCreateKeyEx(HKEY_CURRENT_USER, (LPCTSTR)achTemp, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, &d);
    if (ERROR_SUCCESS != lreturn)
    {
        return AmHresultFromWin32(lreturn);
    }

    wsprintf(achTemp, TEXT("%ls"), szDescription);
    lreturn = RegSetValue(hkey, (LPCTSTR)NULL, REG_SZ, achTemp, sizeof(achTemp));
    if (ERROR_SUCCESS != lreturn)
    {
        RegCloseKey(hkey);
        return AmHresultFromWin32(lreturn);
    }
    HKEY hsubkey;

    wsprintf(achTemp, TEXT("%ls"), szServerType);
    lreturn = RegCreateKeyEx(hkey, achTemp, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hsubkey, &d);
    if (ERROR_SUCCESS != lreturn)
    {
        RegCloseKey(hkey);
        return AmHresultFromWin32(lreturn);
    }
    wsprintf(achTemp, TEXT("%ls"), szFileName);
    lreturn = RegSetValue(hsubkey, (LPCTSTR)NULL, REG_SZ, (LPCTSTR)achTemp, sizeof(TCHAR) * (lstrlen(achTemp) + 1));
    if (ERROR_SUCCESS != lreturn)
    {
        RegCloseKey(hkey);
        RegCloseKey(hsubkey);
        return AmHresultFromWin32(lreturn);
    }
    wsprintf(achTemp, TEXT("%ls"), szThreadingModel);
    lreturn = RegSetValueEx(hsubkey, TEXT("ThreadingModel"), 0L, REG_SZ, (CONST BYTE*)achTemp, sizeof(TCHAR) * (lstrlen(achTemp) + 1));

    RegCloseKey(hkey);
    RegCloseKey(hsubkey);

    ASSERT(SUCCEEDED(hr));
    return HRESULT_FROM_WIN32(lreturn);

}

STDAPI
AMovieSetupUnregisterServerOverride(CLSID clsServer)
{
    OLECHAR szCLSID[CHARS_IN_GUID];
    HRESULT hr = StringFromGUID2(clsServer, szCLSID, CHARS_IN_GUID);
    TCHAR achBuffer[260];
    wsprintf(achBuffer, TEXT("CLSID\\%ls"), szCLSID);
    hr = EliminateSubKey(HKEY_CLASSES_ROOT, achBuffer);
    return NOERROR;
}
这是从winsdk方法复制的,但修改为使用Software\Classes注册表以避免UAC:

AMovieSetupRegisterServer

然后,您可以使用以下代码注册过滤器(注意,我没有完全弄清楚如何序列化过滤器数据,所以我向UAC注册了它,检查了二进制数据是什么,然后手动以这种方式填充。如果您想自己序列化过滤器数据,您可以(方法FilterTemplate::LoadFilterData)


考虑到它在HKEY_LOCAL_MACHINE/Software/Classes/CLSID/下注册,我很确定系统枚举器会检查HKEY_Classes_ROOT/CLSID,除此之外,还有什么原因它不能工作,因为registerfilter函数是硬编码来引用本地机器路径的吗?如果我用und信息编写自己的注册表项er HKEY_当前用户而不是使用::RegisterFilter,因为它与本地计算机类合并,因为HKEY_类根目录不起作用吗?我认为COM注册信息可以进入HKCU,因此您将依赖COM实例化子系统(在CoCreateInstance内)而是从HKCU获取注册数据。这部分可以解决问题。问题是
RegisterFilter
将其他信息写入HKLM,最重要的是,DirectShow Intelligent Connect在那里查找这些信息,而不知道这些数据的一部分也可能在HKCU下。我明白你的意思了我试图这么说,我理解。我并不特别关心intelligent connect;但我认为intelligent connect不工作是系统枚举器未看到筛选器的副产品。我通过组策略设置审核,并使用事件查看器尝试查看正在写入的注册表值,从我的快速测试中可以看出上面提到的注册表值是唯一添加的键。我的理论是,如果我能找出它将REGFILTER2结构转换为二进制FilterData值的顺序,我就可以模拟本地用户的register filter函数FilterData值的格式是已知的(这些应该是序列化数据)。问题是这些值仍在HKLM下,而不是HKCU下。您需要访问权限才能写入这些值,即使您想使用
RegisterFilter
@letmaik刚刚添加的。
// {ae7416c6-637d-4b8e-970d-24af9a1dd02a}
DEFINE_GUID(CLSID_EXAMPLE_GUID,
    0xae7416c6, 0x637d, 0x4b8e, 0x97, 0x0d, 0x24, 0xaf, 0x9a, 0x1d, 0xd0, 0x2a);

HRESULT RegisterCurrentUser(REGFILTER2 rf)
{
    TCHAR achTemp[MAX_PATH];

    OLECHAR szCLSID[CHARS_IN_GUID];
    HRESULT hr = StringFromGUID2(CLSID_EXAMPLE_GUID, szCLSID, CHARS_IN_GUID);

    HKEY hkey;
    wsprintf(achTemp, TEXT("Software\\Classes\\CLSID\\{860BB310-5D01-11d0-BD3B-00A0C911CE86}\\Instance\\%ls"), szCLSID);
    hr = RegCreateKey(HKEY_CURRENT_USER, (LPCTSTR)achTemp, &hkey);

    wsprintf(achTemp, TEXT("%ls"), szCLSID);
    hr = RegSetValueEx(hkey, TEXT("CLSID"), 0L, REG_SZ, (CONST BYTE*) achTemp, sizeof(TCHAR) * (lstrlen(achTemp) + 1));

    DWORD data[20];
    data[0] = 0x00000002; //Version
    data[1] = 0x00200000; //Merit
    data[2] = 0x00000001; //if v===1, pin#
    data[3] = 0x00000000; //if v==2, pin #
    data[4] = 0x33697030;
    data[5] = 0x08000000;
    data[6] = 0x00000000;
    data[7] = 0x00000001;
    data[8] = 0x00000000;
    data[9] = 0x00000000;
    data[10] = 0x33797430;
    data[11] = 0x00000000;
    data[12] = 0x00000038;
    data[13] = 0x00000048;
    data[14] = 0x73646976;
    data[15] = 0x00100000;
    data[16] = 0xAA000080;
    data[17] = 0x719B3800;
    data[18] = 0x00000000;
    data[19] = 0x00000000;


    hr = RegSetValueEx(hkey, TEXT("FilterData"), 0L, REG_BINARY, (BYTE*)data, sizeof(data));

    wsprintf(achTemp, TEXT("%ls"), L"Example Filter");
    hr = RegSetValueEx(hkey, TEXT("FriendlyName"), 0L, REG_SZ, (CONST BYTE*) achTemp, sizeof(TCHAR) * (lstrlen(achTemp) + 1));
    return hr;
}