devenum: Implement parsing and reading DMO monikers.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
62296c56c9
commit
0da4892b45
@ -1,5 +1,5 @@
|
|||||||
MODULE = devenum.dll
|
MODULE = devenum.dll
|
||||||
IMPORTS = strmiids uuid ole32 oleaut32 avicap32 winmm user32 advapi32 dsound
|
IMPORTS = strmiids uuid ole32 oleaut32 avicap32 winmm user32 advapi32 dsound msdmo
|
||||||
DELAYIMPORTS = msvfw32
|
DELAYIMPORTS = msvfw32
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
|
@ -64,6 +64,7 @@ enum device_type
|
|||||||
{
|
{
|
||||||
DEVICE_FILTER,
|
DEVICE_FILTER,
|
||||||
DEVICE_CODEC,
|
DEVICE_CODEC,
|
||||||
|
DEVICE_DMO,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -73,7 +74,11 @@ typedef struct
|
|||||||
CLSID class;
|
CLSID class;
|
||||||
BOOL has_class;
|
BOOL has_class;
|
||||||
enum device_type type;
|
enum device_type type;
|
||||||
WCHAR *name;
|
union
|
||||||
|
{
|
||||||
|
WCHAR *name; /* for filters and codecs */
|
||||||
|
CLSID clsid; /* for DMOs */
|
||||||
|
};
|
||||||
} MediaCatMoniker;
|
} MediaCatMoniker;
|
||||||
|
|
||||||
MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void) DECLSPEC_HIDDEN;
|
MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void) DECLSPEC_HIDDEN;
|
||||||
@ -95,5 +100,8 @@ static const WCHAR wszActiveMovieKey[] = {'S','o','f','t','w','a','r','e','\\',
|
|||||||
'A','c','t','i','v','e','M','o','v','i','e','\\',
|
'A','c','t','i','v','e','M','o','v','i','e','\\',
|
||||||
'd','e','v','e','n','u','m','\\',0};
|
'd','e','v','e','n','u','m','\\',0};
|
||||||
static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':',0};
|
static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':',0};
|
||||||
|
static const WCHAR dmoW[] = {'d','m','o',':',0};
|
||||||
|
static const WCHAR swW[] = {'s','w',':',0};
|
||||||
|
static const WCHAR cmW[] = {'c','m',':',0};
|
||||||
|
|
||||||
extern const WCHAR clsid_keyname[6] DECLSPEC_HIDDEN;
|
extern const WCHAR clsid_keyname[6] DECLSPEC_HIDDEN;
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "devenum_private.h"
|
#include "devenum_private.h"
|
||||||
#include "oleauto.h"
|
#include "oleauto.h"
|
||||||
#include "ocidl.h"
|
#include "ocidl.h"
|
||||||
|
#include "dmoreg.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
@ -46,7 +47,11 @@ typedef struct
|
|||||||
IPropertyBag IPropertyBag_iface;
|
IPropertyBag IPropertyBag_iface;
|
||||||
LONG ref;
|
LONG ref;
|
||||||
enum device_type type;
|
enum device_type type;
|
||||||
WCHAR path[MAX_PATH];
|
union
|
||||||
|
{
|
||||||
|
WCHAR path[MAX_PATH]; /* for filters and codecs */
|
||||||
|
CLSID clsid; /* for DMOs */
|
||||||
|
};
|
||||||
} RegPropBagImpl;
|
} RegPropBagImpl;
|
||||||
|
|
||||||
|
|
||||||
@ -114,12 +119,14 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
|
|||||||
VARIANT* pVar,
|
VARIANT* pVar,
|
||||||
IErrorLog* pErrorLog)
|
IErrorLog* pErrorLog)
|
||||||
{
|
{
|
||||||
|
static const WCHAR FriendlyNameW[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
|
||||||
LPVOID pData = NULL;
|
LPVOID pData = NULL;
|
||||||
DWORD received;
|
DWORD received;
|
||||||
DWORD type = 0;
|
DWORD type = 0;
|
||||||
RegPropBagImpl *This = impl_from_IPropertyBag(iface);
|
RegPropBagImpl *This = impl_from_IPropertyBag(iface);
|
||||||
HRESULT res = S_OK;
|
HRESULT res = S_OK;
|
||||||
LONG reswin32 = ERROR_SUCCESS;
|
LONG reswin32 = ERROR_SUCCESS;
|
||||||
|
WCHAR name[80];
|
||||||
HKEY hkey;
|
HKEY hkey;
|
||||||
|
|
||||||
TRACE("(%p)->(%s, %p, %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog);
|
TRACE("(%p)->(%s, %p, %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog);
|
||||||
@ -127,6 +134,21 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
|
|||||||
if (!pszPropName || !pVar)
|
if (!pszPropName || !pVar)
|
||||||
return E_POINTER;
|
return E_POINTER;
|
||||||
|
|
||||||
|
if (This->type == DEVICE_DMO)
|
||||||
|
{
|
||||||
|
if (!strcmpW(pszPropName, FriendlyNameW))
|
||||||
|
{
|
||||||
|
res = DMOGetName(&This->clsid, name);
|
||||||
|
if (SUCCEEDED(res))
|
||||||
|
{
|
||||||
|
V_VT(pVar) = VT_BSTR;
|
||||||
|
V_BSTR(pVar) = SysAllocString(name);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
if (This->type == DEVICE_FILTER)
|
if (This->type == DEVICE_FILTER)
|
||||||
reswin32 = RegOpenKeyW(HKEY_CLASSES_ROOT, This->path, &hkey);
|
reswin32 = RegOpenKeyW(HKEY_CLASSES_ROOT, This->path, &hkey);
|
||||||
else if (This->type == DEVICE_CODEC)
|
else if (This->type == DEVICE_CODEC)
|
||||||
@ -246,6 +268,9 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Write(
|
|||||||
|
|
||||||
TRACE("(%p)->(%s, %p)\n", This, debugstr_w(pszPropName), pVar);
|
TRACE("(%p)->(%s, %p)\n", This, debugstr_w(pszPropName), pVar);
|
||||||
|
|
||||||
|
if (This->type == DEVICE_DMO)
|
||||||
|
return E_ACCESSDENIED;
|
||||||
|
|
||||||
switch (V_VT(pVar))
|
switch (V_VT(pVar))
|
||||||
{
|
{
|
||||||
case VT_BSTR:
|
case VT_BSTR:
|
||||||
@ -316,18 +341,29 @@ static HRESULT create_PropertyBag(MediaCatMoniker *mon, IPropertyBag **ppBag)
|
|||||||
rpb->ref = 1;
|
rpb->ref = 1;
|
||||||
rpb->type = mon->type;
|
rpb->type = mon->type;
|
||||||
|
|
||||||
if (rpb->type == DEVICE_FILTER)
|
if (rpb->type == DEVICE_DMO)
|
||||||
|
rpb->clsid = mon->clsid;
|
||||||
|
else if (rpb->type == DEVICE_FILTER)
|
||||||
|
{
|
||||||
strcpyW(rpb->path, clsidW);
|
strcpyW(rpb->path, clsidW);
|
||||||
else if (rpb->type == DEVICE_CODEC)
|
|
||||||
strcpyW(rpb->path, wszActiveMovieKey);
|
|
||||||
if (mon->has_class)
|
if (mon->has_class)
|
||||||
{
|
{
|
||||||
StringFromGUID2(&mon->class, rpb->path + strlenW(rpb->path), CHARS_IN_GUID);
|
StringFromGUID2(&mon->class, rpb->path + strlenW(rpb->path), CHARS_IN_GUID);
|
||||||
if (rpb->type == DEVICE_FILTER)
|
|
||||||
strcatW(rpb->path, instanceW);
|
strcatW(rpb->path, instanceW);
|
||||||
strcatW(rpb->path, backslashW);
|
strcatW(rpb->path, backslashW);
|
||||||
}
|
}
|
||||||
strcatW(rpb->path, mon->name);
|
strcatW(rpb->path, mon->name);
|
||||||
|
}
|
||||||
|
else if (rpb->type == DEVICE_CODEC)
|
||||||
|
{
|
||||||
|
strcpyW(rpb->path, wszActiveMovieKey);
|
||||||
|
if (mon->has_class)
|
||||||
|
{
|
||||||
|
StringFromGUID2(&mon->class, rpb->path + strlenW(rpb->path), CHARS_IN_GUID);
|
||||||
|
strcatW(rpb->path, backslashW);
|
||||||
|
}
|
||||||
|
strcatW(rpb->path, mon->name);
|
||||||
|
}
|
||||||
|
|
||||||
*ppBag = &rpb->IPropertyBag_iface;
|
*ppBag = &rpb->IPropertyBag_iface;
|
||||||
DEVENUM_LockModule();
|
DEVENUM_LockModule();
|
||||||
@ -658,8 +694,6 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_RelativePathTo(IMoniker *iface, I
|
|||||||
static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
|
static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
|
||||||
IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
|
IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
|
||||||
{
|
{
|
||||||
static const WCHAR swW[] = {'s','w',':',0};
|
|
||||||
static const WCHAR cmW[] = {'c','m',':',0};
|
|
||||||
MediaCatMoniker *This = impl_from_IMoniker(iface);
|
MediaCatMoniker *This = impl_from_IMoniker(iface);
|
||||||
WCHAR *buffer;
|
WCHAR *buffer;
|
||||||
|
|
||||||
@ -667,10 +701,22 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetDisplayName(IMoniker *iface, I
|
|||||||
|
|
||||||
*ppszDisplayName = NULL;
|
*ppszDisplayName = NULL;
|
||||||
|
|
||||||
buffer = CoTaskMemAlloc((strlenW(deviceW) + 4 + (This->has_class ? CHARS_IN_GUID : 0)
|
if (This->type == DEVICE_DMO)
|
||||||
|
{
|
||||||
|
buffer = CoTaskMemAlloc((strlenW(deviceW) + strlenW(dmoW)
|
||||||
|
+ 2 * CHARS_IN_GUID + 1) * sizeof(WCHAR));
|
||||||
|
if (!buffer) return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
strcpyW(buffer, deviceW);
|
||||||
|
strcatW(buffer, dmoW);
|
||||||
|
StringFromGUID2(&This->clsid, buffer + strlenW(buffer), CHARS_IN_GUID);
|
||||||
|
StringFromGUID2(&This->class, buffer + strlenW(buffer), CHARS_IN_GUID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer = CoTaskMemAlloc((strlenW(deviceW) + 3 + (This->has_class ? CHARS_IN_GUID : 0)
|
||||||
+ strlenW(This->name) + 1) * sizeof(WCHAR));
|
+ strlenW(This->name) + 1) * sizeof(WCHAR));
|
||||||
if (!buffer)
|
if (!buffer) return E_OUTOFMEMORY;
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
|
|
||||||
strcpyW(buffer, deviceW);
|
strcpyW(buffer, deviceW);
|
||||||
if (This->type == DEVICE_FILTER)
|
if (This->type == DEVICE_FILTER)
|
||||||
@ -684,6 +730,7 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetDisplayName(IMoniker *iface, I
|
|||||||
strcatW(buffer, backslashW);
|
strcatW(buffer, backslashW);
|
||||||
}
|
}
|
||||||
strcatW(buffer, This->name);
|
strcatW(buffer, This->name);
|
||||||
|
}
|
||||||
|
|
||||||
*ppszDisplayName = buffer;
|
*ppszDisplayName = buffer;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -91,16 +91,21 @@ static HRESULT WINAPI DEVENUM_IParseDisplayName_ParseDisplayName(IParseDisplayNa
|
|||||||
|
|
||||||
name = strchrW(name, ':') + 1;
|
name = strchrW(name, ':') + 1;
|
||||||
|
|
||||||
if (name[0] == 's' && name[1] == 'w' && name[2] == ':')
|
if (!strncmpW(name, swW, 3))
|
||||||
{
|
{
|
||||||
type = DEVICE_FILTER;
|
type = DEVICE_FILTER;
|
||||||
name += 3;
|
name += 3;
|
||||||
}
|
}
|
||||||
else if (name[0] == 'c' && name[1] == 'm' && name[2] == ':')
|
else if (!strncmpW(name, cmW, 3))
|
||||||
{
|
{
|
||||||
type = DEVICE_CODEC;
|
type = DEVICE_CODEC;
|
||||||
name += 3;
|
name += 3;
|
||||||
}
|
}
|
||||||
|
else if (!strncmpW(name, dmoW, 4))
|
||||||
|
{
|
||||||
|
type = DEVICE_DMO;
|
||||||
|
name += 4;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FIXME("unhandled device type %s\n", debugstr_w(name));
|
FIXME("unhandled device type %s\n", debugstr_w(name));
|
||||||
@ -110,6 +115,24 @@ static HRESULT WINAPI DEVENUM_IParseDisplayName_ParseDisplayName(IParseDisplayNa
|
|||||||
if (!(mon = DEVENUM_IMediaCatMoniker_Construct()))
|
if (!(mon = DEVENUM_IMediaCatMoniker_Construct()))
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
if (type == DEVICE_DMO)
|
||||||
|
{
|
||||||
|
lstrcpynW(buffer, name, CHARS_IN_GUID);
|
||||||
|
if (FAILED(CLSIDFromString(buffer, &mon->clsid)))
|
||||||
|
{
|
||||||
|
IMoniker_Release(&mon->IMoniker_iface);
|
||||||
|
return MK_E_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
lstrcpynW(buffer, name + CHARS_IN_GUID - 1, CHARS_IN_GUID);
|
||||||
|
if (FAILED(CLSIDFromString(buffer, &mon->class)))
|
||||||
|
{
|
||||||
|
IMoniker_Release(&mon->IMoniker_iface);
|
||||||
|
return MK_E_SYNTAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
lstrcpynW(buffer, name, CHARS_IN_GUID);
|
lstrcpynW(buffer, name, CHARS_IN_GUID);
|
||||||
if (CLSIDFromString(buffer, &class) == S_OK)
|
if (CLSIDFromString(buffer, &class) == S_OK)
|
||||||
{
|
{
|
||||||
@ -118,14 +141,15 @@ static HRESULT WINAPI DEVENUM_IParseDisplayName_ParseDisplayName(IParseDisplayNa
|
|||||||
name += CHARS_IN_GUID;
|
name += CHARS_IN_GUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
mon->type = type;
|
|
||||||
|
|
||||||
if (!(mon->name = CoTaskMemAlloc((strlenW(name) + 1) * sizeof(WCHAR))))
|
if (!(mon->name = CoTaskMemAlloc((strlenW(name) + 1) * sizeof(WCHAR))))
|
||||||
{
|
{
|
||||||
IMoniker_Release(&mon->IMoniker_iface);
|
IMoniker_Release(&mon->IMoniker_iface);
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
strcpyW(mon->name, name);
|
strcpyW(mon->name, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
mon->type = type;
|
||||||
|
|
||||||
*ret = &mon->IMoniker_iface;
|
*ret = &mon->IMoniker_iface;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
TESTDLL = devenum.dll
|
TESTDLL = devenum.dll
|
||||||
IMPORTS = advapi32 dsound msvfw32 oleaut32 ole32 winmm
|
IMPORTS = advapi32 dsound msdmo msvfw32 oleaut32 ole32 winmm
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
devenum.c
|
devenum.c
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "dsound.h"
|
#include "dsound.h"
|
||||||
#include "mmddk.h"
|
#include "mmddk.h"
|
||||||
#include "vfw.h"
|
#include "vfw.h"
|
||||||
|
#include "dmoreg.h"
|
||||||
|
|
||||||
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
|
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
|
||||||
|
|
||||||
@ -41,6 +42,7 @@ static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':',0};
|
|||||||
static const WCHAR clsidW[] = {'C','L','S','I','D',0};
|
static const WCHAR clsidW[] = {'C','L','S','I','D',0};
|
||||||
static const WCHAR waveW[] = {'w','a','v','e',':',0};
|
static const WCHAR waveW[] = {'w','a','v','e',':',0};
|
||||||
static const WCHAR mrleW[] = {'m','r','l','e',0};
|
static const WCHAR mrleW[] = {'m','r','l','e',0};
|
||||||
|
static const WCHAR dmoW[] = {'d','m','o',':',0};
|
||||||
static const WCHAR swW[] = {'s','w',':',0};
|
static const WCHAR swW[] = {'s','w',':',0};
|
||||||
static const WCHAR cmW[] = {'c','m',':',0};
|
static const WCHAR cmW[] = {'c','m',':',0};
|
||||||
static const WCHAR backslashW[] = {'\\',0};
|
static const WCHAR backslashW[] = {'\\',0};
|
||||||
@ -485,6 +487,67 @@ static void test_codec(void)
|
|||||||
IParseDisplayName_Release(parser);
|
IParseDisplayName_Release(parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_dmo(void)
|
||||||
|
{
|
||||||
|
static const WCHAR name[] = {'d','e','v','e','n','u','m',' ','t','e','s','t',0};
|
||||||
|
IParseDisplayName *parser;
|
||||||
|
IPropertyBag *prop_bag;
|
||||||
|
WCHAR buffer[200];
|
||||||
|
IMoniker *mon;
|
||||||
|
VARIANT var;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser);
|
||||||
|
ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);
|
||||||
|
|
||||||
|
lstrcpyW(buffer, deviceW);
|
||||||
|
lstrcatW(buffer, dmoW);
|
||||||
|
StringFromGUID2(&CLSID_TestFilter, buffer + lstrlenW(buffer), CHARS_IN_GUID);
|
||||||
|
StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
|
||||||
|
mon = check_display_name(parser, buffer);
|
||||||
|
|
||||||
|
ok(!find_moniker(&CLSID_AudioRendererCategory, mon), "DMO should not be registered\n");
|
||||||
|
|
||||||
|
hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
|
||||||
|
ok(hr == S_OK, "got %#x\n", hr);
|
||||||
|
|
||||||
|
VariantInit(&var);
|
||||||
|
hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
|
||||||
|
ok(hr == E_FAIL, "got %#x\n", hr);
|
||||||
|
|
||||||
|
V_VT(&var) = VT_BSTR;
|
||||||
|
V_BSTR(&var) = SysAllocString(name);
|
||||||
|
hr = IPropertyBag_Write(prop_bag, friendly_name, &var);
|
||||||
|
ok(hr == E_ACCESSDENIED, "Write failed: %#x\n", hr);
|
||||||
|
|
||||||
|
hr = DMORegister(name, &CLSID_TestFilter, &CLSID_AudioRendererCategory, 0, 0, NULL, 0, NULL);
|
||||||
|
if (hr != E_ACCESSDENIED)
|
||||||
|
{
|
||||||
|
ok(hr == S_OK, "got %#x\n", hr);
|
||||||
|
|
||||||
|
VariantClear(&var);
|
||||||
|
hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
|
||||||
|
ok(hr == S_OK, "got %#x\n", hr);
|
||||||
|
ok(!lstrcmpW(V_BSTR(&var), name), "got %s\n", wine_dbgstr_w(V_BSTR(&var)));
|
||||||
|
|
||||||
|
VariantClear(&var);
|
||||||
|
V_VT(&var) = VT_BSTR;
|
||||||
|
V_BSTR(&var) = SysAllocString(name);
|
||||||
|
hr = IPropertyBag_Write(prop_bag, friendly_name, &var);
|
||||||
|
ok(hr == E_ACCESSDENIED, "Write failed: %#x\n", hr);
|
||||||
|
|
||||||
|
VariantClear(&var);
|
||||||
|
hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL);
|
||||||
|
ok(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "got %#x\n", hr);
|
||||||
|
|
||||||
|
hr = DMOUnregister(&CLSID_TestFilter, &CLSID_AudioRendererCategory);
|
||||||
|
ok(hr == S_OK, "got %#x\n", hr);
|
||||||
|
}
|
||||||
|
IPropertyBag_Release(prop_bag);
|
||||||
|
IMoniker_Release(mon);
|
||||||
|
IParseDisplayName_Release(parser);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_legacy_filter(void)
|
static void test_legacy_filter(void)
|
||||||
{
|
{
|
||||||
static const WCHAR nameW[] = {'t','e','s','t',0};
|
static const WCHAR nameW[] = {'t','e','s','t',0};
|
||||||
@ -974,6 +1037,7 @@ START_TEST(devenum)
|
|||||||
test_register_filter();
|
test_register_filter();
|
||||||
test_directshow_filter();
|
test_directshow_filter();
|
||||||
test_codec();
|
test_codec();
|
||||||
|
test_dmo();
|
||||||
|
|
||||||
test_legacy_filter();
|
test_legacy_filter();
|
||||||
hr = DirectSoundEnumerateW(test_dsound, NULL);
|
hr = DirectSoundEnumerateW(test_dsound, NULL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user