您可以在没有管理员的情况下注册DirectShow过滤器吗?

问题描述

我想在不需要管理员的情况下注册虚拟DirectShow源设备。在另一篇文章中,我看到有人提到您可以通过HKEY_CURRENT_USER(而不是HKEY_CLASSES_ROOT或HKEY_LOCAL_MACHINE)为每个用户帐户注册COM类。这行得通,我可以在没有UAC的情况下通过HKEY_CURRENT_USER \ Software \ Classes注册该类。

要显示源/过滤器,我需要致电IFilterMapper2::RegisterFilter。没有UAC特权,此操作将失败。 (E_ACCESSDENIED General access denied error.)。

Microsoft不清楚对RegisterFilter的调用实际上是做什么的。我知道它会在HKEY_CLASSES_ROOT\CLSID\category clsid\Instance\filter clsid下创建一个注册表项,但关键值之一是FilterData,它是一个二进制值,理论上应与该结构的https://docs.microsoft.com/en-us/windows/win32/api/strmif/ns-strmif-regfilter2相匹配;但是数据并不完全对齐,因此他们也必须在其中写入其他数据。

反正有没有在用户帐户级别注册过滤器?

解决方法

注册信息位于HKEY_LOCAL_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,NULL,KEY_ALL_ACCESS,&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,szServerType);
    lreturn = RegCreateKeyEx(hkey,&hsubkey,&d);
    if (ERROR_SUCCESS != lreturn)
    {
        RegCloseKey(hkey);
        return AmHresultFromWin32(lreturn);
    }
    wsprintf(achTemp,szFileName);
    lreturn = RegSetValue(hsubkey,sizeof(TCHAR) * (lstrlen(achTemp) + 1));
    if (ERROR_SUCCESS != lreturn)
    {
        RegCloseKey(hkey);
        RegCloseKey(hsubkey);
        return AmHresultFromWin32(lreturn);
    }
    wsprintf(achTemp,szThreadingModel);
    lreturn = RegSetValueEx(hsubkey,TEXT("ThreadingModel"),0L,(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,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

Found Here

然后您可以使用以下代码注册过滤器(注意,我没有完全弄清楚如何序列化过滤器数据,所以我使用 UAC 注册它,检查二进制数据是什么,然后手动填充它那样。如果你想自己序列化过滤器数据,你可以reverse how they do it in GraphStudioNext(方法FilterTemplate::LoadFilterData)

// {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,CHARS_IN_GUID);

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

    wsprintf(achTemp,szCLSID);
    hr = RegSetValueEx(hkey,TEXT("CLSID"),(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"),REG_BINARY,(BYTE*)data,sizeof(data));

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

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...