从应用程序中的 GRF 文件加载 Directshow IFilterGraphs 对于在 DLL 中全局注册的普通过滤器效果很好。
// open structured storage file...
hr = pStorage->OpenStream(L"ActiveMovieGraph", 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream);
if (SUCCEEDED(hr)) {
hr = pPersistStream->Load(pStream);
pStream->Release();
}
然而,一些过滤器是使用从 IClassFactory 实现调用的 CoRegisterObject 在 EXE 中本地注册的。当 IClassFactory 实现收到 IClassFactory::CreateInstance 调用时,这些过滤器是用 C++ new 创建的。
HRESULT hr = CoRegisterClassObject(*m_pTemplate->m_ClsID, this, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &m_RegisterKey);
当直接通过 CoCreateInstance 创建时,本地过滤器工作正常。当直接使用 C++ new 创建时,它们也可以正常工作。
CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&instance);
加载包含这些本地过滤器的 GRF 文件不起作用并返回 HRESULT 0x80040154 未从 IPersistStream::Load 注册的类。
未调用应用程序的 IClassFactory::CreateInstance 函数,但在 IPersistStream::Load 期间使用正确的 CLSID 调用 CoCreateInstance API,但它是从与 IPersistStream::Load 调用不同的线程调用的(在使用 COM 单元线程初始化的主应用程序线程上)。另一个区别是从 IPersistStream::Load 调用时 dwContext 是 CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER。然而,来自主线程的 CoCreateInstance 调用仍然使用这个 dwContext 值。包括 CLSCTX_INPROC_HANDLER 标志的 CoRegisterClassObject 调用因 E_INVALIDARG 而失败。
ole32.dll!CoCreateInstance(const _GUID & rclsid, IUnknown * pUnkOuter, unsigned long dwContext, const _GUID & riid, void * * ppv) Line 96 C++
quartz.dll!_CoCreateFilter@8() + 0x1a bytes
quartz.dll!CFilterGraph::OnCreateFilter() + 0x55 bytes
quartz.dll!CFGControl::CGraphWindow::OnReceiveMessage() + 0x2d05 bytes
quartz.dll!WndProc() + 0x3e bytes
user32.dll!_InternalCallWinProc@20() + 0x23 bytes
user32.dll!_UserCallWinProcCheckWow@32() + 0xb7 bytes
user32.dll!_DispatchMessageWorker@8() + 0xed bytes
user32.dll!_DispatchMessageW@4() + 0xf bytes
quartz.dll!ObjectThread() + 0x65 bytes
kernel32.dll!@BaseThreadInitThunk@12() + 0x12 bytes
ntdll.dll!___RtlUserThreadStart@8() + 0x27 bytes
ntdll.dll!__RtlUserThreadStart@8() + 0x1b bytes
rclsid {CA6B3460-28B3-4A6E-A7FC-A83CF1DEEC49} const _GUID &
pUnkOuter 0x00000000 IUnknown *
dwContext 3 unsigned long
riid {IID_IBaseFilter} const _GUID &
应用程序按照 MFC 应用程序的建议调用 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)。我尝试在对 CoRegisterClassObject 的调用中使用不同的上下文和标志值,但没有成功。GRF 文件肯定包含进程本地过滤器的正确 CLSID。
该行为与应用程序的 Win32 和 x64 版本相同。主机操作系统是 Windows 7 x64。
IFilterGraph 序列化是否支持使用 CoRegisterClassObject 注册的进程本地过滤器?如果是这样,应用程序正在做什么有问题吗?我可以采取任何步骤来进一步诊断此问题吗?