[DEVENUM] Sync with Wine Staging 3.9. CORE-14656

This commit is contained in:
Amine Khaldi 2018-05-27 03:56:13 +01:00
parent e00ccd4551
commit 5e3341f4bb
8 changed files with 866 additions and 729 deletions

View file

@ -4,6 +4,7 @@ add_definitions(-D_WIN32_WINNT=0x600 -DWINVER=0x600)
add_definitions(-D__WINESRC__) add_definitions(-D__WINESRC__)
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine)
add_idl_headers(devenum_fil_data_header fil_data.idl)
spec2def(devenum.dll devenum.spec) spec2def(devenum.dll devenum.spec)
list(APPEND SOURCE list(APPEND SOURCE
@ -23,6 +24,7 @@ set_source_files_properties(devenum.rc PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT
set_module_type(devenum win32dll UNICODE) set_module_type(devenum win32dll UNICODE)
target_link_libraries(devenum strmiids uuid wine) target_link_libraries(devenum strmiids uuid wine)
add_delay_importlibs(devenum msvfw32) add_delay_importlibs(devenum msvfw32)
add_importlibs(devenum advapi32 advapi32_vista ole32 oleaut32 winmm user32 avicap32 msacm32 msvcrt kernel32 ntdll) add_importlibs(devenum advapi32 advapi32_vista ole32 oleaut32 winmm user32 avicap32 msacm32 dsound msvcrt kernel32 ntdll)
add_dependencies(devenum devenum_fil_data_header)
add_pch(devenum precomp.h SOURCE) add_pch(devenum precomp.h SOURCE)
add_cd_file(TARGET devenum DESTINATION reactos/system32 FOR all) add_cd_file(TARGET devenum DESTINATION reactos/system32 FOR all)

File diff suppressed because it is too large Load diff

View file

@ -23,18 +23,6 @@
#include "winnls.h" #include "winnls.h"
#include "devenum_private.h" #include "devenum_private.h"
#pragma makedep po
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
STRINGTABLE
{
IDS_DEVENUM_DSDEFAULT "Default DirectSound"
IDS_DEVENUM_DS "DirectSound: %s"
IDS_DEVENUM_WODEFAULT "Default WaveOut Device"
IDS_DEVENUM_MIDEFAULT "Default MidiOut Device"
}
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#define WINE_FILEDESCRIPTION_STR "Wine Device Enumerator Library" #define WINE_FILEDESCRIPTION_STR "Wine Device Enumerator Library"

View file

@ -62,38 +62,40 @@ typedef struct
IClassFactory IClassFactory_iface; IClassFactory IClassFactory_iface;
} ClassFactoryImpl; } ClassFactoryImpl;
enum device_type
{
DEVICE_FILTER,
DEVICE_CODEC,
};
typedef struct typedef struct
{ {
IMoniker IMoniker_iface; IMoniker IMoniker_iface;
LONG ref; LONG ref;
HKEY hkey; CLSID class;
BOOL has_class;
enum device_type type;
WCHAR *name;
} MediaCatMoniker; } MediaCatMoniker;
MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void) DECLSPEC_HIDDEN; MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void) DECLSPEC_HIDDEN;
HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, HKEY special_hkey, IEnumMoniker ** ppEnumMoniker) DECLSPEC_HIDDEN; HRESULT create_EnumMoniker(REFCLSID class, IEnumMoniker **enum_mon) DECLSPEC_HIDDEN;
extern ClassFactoryImpl DEVENUM_ClassFactory DECLSPEC_HIDDEN; extern ClassFactoryImpl DEVENUM_ClassFactory DECLSPEC_HIDDEN;
extern ICreateDevEnum DEVENUM_CreateDevEnum DECLSPEC_HIDDEN; extern ICreateDevEnum DEVENUM_CreateDevEnum DECLSPEC_HIDDEN;
extern IParseDisplayName DEVENUM_ParseDisplayName DECLSPEC_HIDDEN; extern IParseDisplayName DEVENUM_ParseDisplayName DECLSPEC_HIDDEN;
/**********************************************************************
* Private helper function to get AM filter category key location
*/
HRESULT DEVENUM_GetCategoryKey(REFCLSID clsidDeviceClass, HKEY *pBaseKey, WCHAR *wszRegKeyName, UINT maxLen) DECLSPEC_HIDDEN;
/********************************************************************** /**********************************************************************
* Global string constant declarations * Global string constant declarations
*/ */
extern const WCHAR clsid_keyname[6] DECLSPEC_HIDDEN;
extern const WCHAR wszInstanceKeyName[] DECLSPEC_HIDDEN;
#define CLSID_STR_LEN (sizeof(clsid_keyname) / sizeof(WCHAR))
/********************************************************************** static const WCHAR backslashW[] = {'\\',0};
* Resource IDs static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0};
*/ static const WCHAR instanceW[] = {'\\','I','n','s','t','a','n','c','e',0};
#define IDS_DEVENUM_DSDEFAULT 7 static const WCHAR wszActiveMovieKey[] = {'S','o','f','t','w','a','r','e','\\',
#define IDS_DEVENUM_DS 8 'M','i','c','r','o','s','o','f','t','\\',
#define IDS_DEVENUM_WODEFAULT 9 'A','c','t','i','v','e','M','o','v','i','e','\\',
#define IDS_DEVENUM_MIDEFAULT 10 'd','e','v','e','n','u','m','\\',0};
#define IDS_DEVENUM_KSDEFAULT 11 static const WCHAR deviceW[] = {'@','d','e','v','i','c','e',':',0};
#define IDS_DEVENUM_KS 12
extern const WCHAR clsid_keyname[6] DECLSPEC_HIDDEN;

View file

@ -0,0 +1,47 @@
/*
* Copyright (C) 2009 Vitaliy Margolen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#pragma makedep header
import "objidl.idl";
import "strmif.idl";
import "unknwn.idl";
/*****************************************************************************
* IAMFilterData interface
*/
[
object,
uuid(97f7c4d4-547b-4a5f-8332-536430ad2e4d),
pointer_default(unique)
]
interface IAMFilterData : IUnknown
{
typedef [unique] IAMFilterData *LPIAMFILTERDATA;
HRESULT ParseFilterData(
[in] BYTE * rgbFilterData,
[in] ULONG cb,
[out] BYTE ** prgbRegFilter2);
HRESULT CreateFilterData(
[in] REGFILTER2 * prf2,
[out] BYTE ** prgbFilterData,
[out] ULONG * pcb);
}

View file

@ -33,18 +33,20 @@ WINE_DEFAULT_DEBUG_CHANNEL(devenum);
typedef struct typedef struct
{ {
IEnumMoniker IEnumMoniker_iface; IEnumMoniker IEnumMoniker_iface;
CLSID class;
LONG ref; LONG ref;
DWORD index; HKEY sw_key;
DWORD subkey_cnt; DWORD sw_index;
HKEY hkey; HKEY cm_key;
HKEY special_hkey; DWORD cm_index;
} EnumMonikerImpl; } EnumMonikerImpl;
typedef struct typedef struct
{ {
IPropertyBag IPropertyBag_iface; IPropertyBag IPropertyBag_iface;
LONG ref; LONG ref;
HKEY hkey; enum device_type type;
WCHAR path[MAX_PATH];
} RegPropBagImpl; } RegPropBagImpl;
@ -100,7 +102,6 @@ static ULONG WINAPI DEVENUM_IPropertyBag_Release(LPPROPERTYBAG iface)
ref = InterlockedDecrement(&This->ref); ref = InterlockedDecrement(&This->ref);
if (ref == 0) { if (ref == 0) {
RegCloseKey(This->hkey);
CoTaskMemFree(This); CoTaskMemFree(This);
DEVENUM_UnlockModule(); DEVENUM_UnlockModule();
} }
@ -118,22 +119,32 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
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; LONG reswin32 = ERROR_SUCCESS;
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);
if (!pszPropName || !pVar) if (!pszPropName || !pVar)
return E_POINTER; return E_POINTER;
reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, NULL, NULL, &received); if (This->type == DEVICE_FILTER)
reswin32 = RegOpenKeyW(HKEY_CLASSES_ROOT, This->path, &hkey);
else if (This->type == DEVICE_CODEC)
reswin32 = RegOpenKeyW(HKEY_CURRENT_USER, This->path, &hkey);
res = HRESULT_FROM_WIN32(reswin32); res = HRESULT_FROM_WIN32(reswin32);
if (SUCCEEDED(res))
{
reswin32 = RegQueryValueExW(hkey, pszPropName, NULL, NULL, NULL, &received);
res = HRESULT_FROM_WIN32(reswin32);
}
if (SUCCEEDED(res)) if (SUCCEEDED(res))
{ {
pData = HeapAlloc(GetProcessHeap(), 0, received); pData = HeapAlloc(GetProcessHeap(), 0, received);
/* work around a GCC bug that occurs here unless we use the reswin32 variable as well */ /* work around a GCC bug that occurs here unless we use the reswin32 variable as well */
reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, &type, pData, &received); reswin32 = RegQueryValueExW(hkey, pszPropName, NULL, &type, pData, &received);
res = HRESULT_FROM_WIN32(reswin32); res = HRESULT_FROM_WIN32(reswin32);
} }
@ -214,6 +225,8 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
HeapFree(GetProcessHeap(), 0, pData); HeapFree(GetProcessHeap(), 0, pData);
RegCloseKey(hkey);
TRACE("<- %x\n", res); TRACE("<- %x\n", res);
return res; return res;
} }
@ -228,6 +241,8 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Write(
DWORD cbData = 0; DWORD cbData = 0;
DWORD dwType = 0; DWORD dwType = 0;
HRESULT res = S_OK; HRESULT res = S_OK;
LONG lres = ERROR_SUCCESS;
HKEY hkey;
TRACE("(%p)->(%s, %p)\n", This, debugstr_w(pszPropName), pVar); TRACE("(%p)->(%s, %p)\n", This, debugstr_w(pszPropName), pVar);
@ -264,10 +279,18 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Write(
return E_FAIL; return E_FAIL;
} }
if (RegSetValueExW(This->hkey, if (This->type == DEVICE_FILTER)
pszPropName, 0, lres = RegCreateKeyW(HKEY_CLASSES_ROOT, This->path, &hkey);
dwType, lpData, cbData) != ERROR_SUCCESS) else if (This->type == DEVICE_CODEC)
res = E_FAIL; lres = RegCreateKeyW(HKEY_CURRENT_USER, This->path, &hkey);
res = HRESULT_FROM_WIN32(lres);
if (SUCCEEDED(res))
{
lres = RegSetValueExW(hkey, pszPropName, 0, dwType, lpData, cbData);
res = HRESULT_FROM_WIN32(lres);
RegCloseKey(hkey);
}
if (V_VT(pVar) & VT_ARRAY) if (V_VT(pVar) & VT_ARRAY)
res = SafeArrayUnaccessData(V_ARRAY(pVar)); res = SafeArrayUnaccessData(V_ARRAY(pVar));
@ -284,14 +307,28 @@ static const IPropertyBagVtbl IPropertyBag_Vtbl =
DEVENUM_IPropertyBag_Write DEVENUM_IPropertyBag_Write
}; };
static HRESULT DEVENUM_IPropertyBag_Construct(HANDLE hkey, IPropertyBag **ppBag) static HRESULT create_PropertyBag(MediaCatMoniker *mon, IPropertyBag **ppBag)
{ {
RegPropBagImpl * rpb = CoTaskMemAlloc(sizeof(RegPropBagImpl)); RegPropBagImpl * rpb = CoTaskMemAlloc(sizeof(RegPropBagImpl));
if (!rpb) if (!rpb)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
rpb->IPropertyBag_iface.lpVtbl = &IPropertyBag_Vtbl; rpb->IPropertyBag_iface.lpVtbl = &IPropertyBag_Vtbl;
rpb->ref = 1; rpb->ref = 1;
rpb->hkey = hkey; rpb->type = mon->type;
if (rpb->type == DEVICE_FILTER)
strcpyW(rpb->path, clsidW);
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);
if (rpb->type == DEVICE_FILTER)
strcatW(rpb->path, instanceW);
strcatW(rpb->path, backslashW);
}
strcatW(rpb->path, mon->name);
*ppBag = &rpb->IPropertyBag_iface; *ppBag = &rpb->IPropertyBag_iface;
DEVENUM_LockModule(); DEVENUM_LockModule();
return S_OK; return S_OK;
@ -344,7 +381,7 @@ static ULONG WINAPI DEVENUM_IMediaCatMoniker_Release(IMoniker *iface)
TRACE("(%p) ref=%d\n", This, ref); TRACE("(%p) ref=%d\n", This, ref);
if (ref == 0) { if (ref == 0) {
RegCloseKey(This->hkey); CoTaskMemFree(This->name);
CoTaskMemFree(This); CoTaskMemFree(This);
DEVENUM_UnlockModule(); DEVENUM_UnlockModule();
} }
@ -407,6 +444,9 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToObject(IMoniker *iface, IBi
TRACE("(%p)->(%p, %p, %s, %p)\n", This, pbc, pmkToLeft, debugstr_guid(riidResult), ppvResult); TRACE("(%p)->(%p, %p, %s, %p)\n", This, pbc, pmkToLeft, debugstr_guid(riidResult), ppvResult);
if (!ppvResult)
return E_POINTER;
VariantInit(&var); VariantInit(&var);
*ppvResult = NULL; *ppvResult = NULL;
@ -485,9 +525,7 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToStorage(IMoniker *iface, IB
if (IsEqualGUID(riid, &IID_IPropertyBag)) if (IsEqualGUID(riid, &IID_IPropertyBag))
{ {
HANDLE hkey; return create_PropertyBag(This, (IPropertyBag**)ppvObj);
DuplicateHandle(GetCurrentProcess(), This->hkey, GetCurrentProcess(), &hkey, 0, 0, DUPLICATE_SAME_ACCESS);
return DEVENUM_IPropertyBag_Construct(hkey, (IPropertyBag**)ppvObj);
} }
return MK_E_NOSTORAGE; return MK_E_NOSTORAGE;
@ -620,24 +658,35 @@ 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 wszBuffer[MAX_PATH]; WCHAR *buffer;
static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
DWORD received = sizeof(wszBuffer);
TRACE("(%p)->(%p, %p, %p)\n", iface, pbc, pmkToLeft, ppszDisplayName); TRACE("(%p)->(%p, %p, %p)\n", iface, pbc, pmkToLeft, ppszDisplayName);
*ppszDisplayName = NULL; *ppszDisplayName = NULL;
/* FIXME: should this be the weird stuff we have to parse in IParseDisplayName? */ buffer = CoTaskMemAlloc((strlenW(deviceW) + 4 + (This->has_class ? CHARS_IN_GUID : 0)
if (RegQueryValueExW(This->hkey, wszFriendlyName, NULL, NULL, (LPBYTE)wszBuffer, &received) == ERROR_SUCCESS) + strlenW(This->name) + 1) * sizeof(WCHAR));
{ if (!buffer)
*ppszDisplayName = CoTaskMemAlloc(received); return E_OUTOFMEMORY;
strcpyW(*ppszDisplayName, wszBuffer);
return S_OK;
}
return E_FAIL; strcpyW(buffer, deviceW);
if (This->type == DEVICE_FILTER)
strcatW(buffer, swW);
else if (This->type == DEVICE_CODEC)
strcatW(buffer, cmW);
if (This->has_class)
{
StringFromGUID2(&This->class, buffer + strlenW(buffer), CHARS_IN_GUID);
strcatW(buffer, backslashW);
}
strcatW(buffer, This->name);
*ppszDisplayName = buffer;
return S_OK;
} }
static HRESULT WINAPI DEVENUM_IMediaCatMoniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc, static HRESULT WINAPI DEVENUM_IMediaCatMoniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc,
@ -694,7 +743,8 @@ MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void)
pMoniker->IMoniker_iface.lpVtbl = &IMoniker_Vtbl; pMoniker->IMoniker_iface.lpVtbl = &IMoniker_Vtbl;
pMoniker->ref = 0; pMoniker->ref = 0;
pMoniker->hkey = NULL; pMoniker->has_class = FALSE;
pMoniker->name = NULL;
DEVENUM_IMediaCatMoniker_AddRef(&pMoniker->IMoniker_iface); DEVENUM_IMediaCatMoniker_AddRef(&pMoniker->IMoniker_iface);
@ -748,9 +798,8 @@ static ULONG WINAPI DEVENUM_IEnumMoniker_Release(IEnumMoniker *iface)
if (!ref) if (!ref)
{ {
if(This->special_hkey) RegCloseKey(This->sw_key);
RegCloseKey(This->special_hkey); RegCloseKey(This->cm_key);
RegCloseKey(This->hkey);
CoTaskMemFree(This); CoTaskMemFree(This);
DEVENUM_UnlockModule(); DEVENUM_UnlockModule();
return 0; return 0;
@ -766,37 +815,55 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(IEnumMoniker *iface, ULONG celt,
LONG res; LONG res;
ULONG fetched = 0; ULONG fetched = 0;
MediaCatMoniker * pMoniker; MediaCatMoniker * pMoniker;
HKEY hkey;
TRACE("(%p)->(%d, %p, %p)\n", iface, celt, rgelt, pceltFetched); TRACE("(%p)->(%d, %p, %p)\n", iface, celt, rgelt, pceltFetched);
while (fetched < celt) while (fetched < celt)
{ {
if(This->index+fetched < This->subkey_cnt) /* FIXME: try PNP devices and DMOs first */
res = RegEnumKeyW(This->hkey, This->index+fetched, buffer, sizeof(buffer) / sizeof(WCHAR));
else if(This->special_hkey) /* try DirectShow filters */
res = RegEnumKeyW(This->special_hkey, This->index+fetched-This->subkey_cnt, buffer, sizeof(buffer) / sizeof(WCHAR)); if (!(res = RegEnumKeyW(This->sw_key, This->sw_index, buffer, sizeof(buffer)/sizeof(WCHAR))))
{
This->sw_index++;
if ((res = RegOpenKeyExW(This->sw_key, buffer, 0, KEY_QUERY_VALUE, &hkey)))
break;
if (!(pMoniker = DEVENUM_IMediaCatMoniker_Construct()))
return E_OUTOFMEMORY;
pMoniker->type = DEVICE_FILTER;
}
/* then try codecs */
else if (!(res = RegEnumKeyW(This->cm_key, This->cm_index, buffer, sizeof(buffer)/sizeof(WCHAR))))
{
This->cm_index++;
if ((res = RegOpenKeyExW(This->cm_key, buffer, 0, KEY_QUERY_VALUE, &hkey)))
break;
if (!(pMoniker = DEVENUM_IMediaCatMoniker_Construct()))
return E_OUTOFMEMORY;
pMoniker->type = DEVICE_CODEC;
}
else else
break; break;
if (res != ERROR_SUCCESS)
{
break;
}
pMoniker = DEVENUM_IMediaCatMoniker_Construct();
if (!pMoniker)
return E_OUTOFMEMORY;
if (RegOpenKeyW(This->index+fetched < This->subkey_cnt ? This->hkey : This->special_hkey, if (!(pMoniker->name = CoTaskMemAlloc((strlenW(buffer) + 1) * sizeof(WCHAR))))
buffer, &pMoniker->hkey) != ERROR_SUCCESS)
{ {
IMoniker_Release(&pMoniker->IMoniker_iface); IMoniker_Release(&pMoniker->IMoniker_iface);
break; return E_OUTOFMEMORY;
} }
strcpyW(pMoniker->name, buffer);
pMoniker->has_class = TRUE;
pMoniker->class = This->class;
rgelt[fetched] = &pMoniker->IMoniker_iface; rgelt[fetched] = &pMoniker->IMoniker_iface;
fetched++; fetched++;
} }
This->index += fetched;
TRACE("-- fetched %d\n", fetched); TRACE("-- fetched %d\n", fetched);
if (pceltFetched) if (pceltFetched)
@ -811,21 +878,26 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(IEnumMoniker *iface, ULONG celt,
static HRESULT WINAPI DEVENUM_IEnumMoniker_Skip(IEnumMoniker *iface, ULONG celt) static HRESULT WINAPI DEVENUM_IEnumMoniker_Skip(IEnumMoniker *iface, ULONG celt)
{ {
EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
DWORD special_subkeys = 0;
TRACE("(%p)->(%d)\n", iface, celt); TRACE("(%p)->(%d)\n", iface, celt);
/* Before incrementing, check if there are any more values to run through. while (celt--)
Some programs use the Skip() function to get the number of devices */
if(This->special_hkey)
RegQueryInfoKeyW(This->special_hkey, NULL, NULL, NULL, &special_subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if((This->index + celt) >= This->subkey_cnt + special_subkeys)
{ {
return S_FALSE; /* FIXME: try PNP devices and DMOs first */
}
This->index += celt; /* try DirectShow filters */
if (RegEnumKeyW(This->sw_key, This->sw_index, NULL, 0) != ERROR_NO_MORE_ITEMS)
{
This->sw_index++;
}
/* then try codecs */
else if (RegEnumKeyW(This->cm_key, This->cm_index, NULL, 0) != ERROR_NO_MORE_ITEMS)
{
This->cm_index++;
}
else
return S_FALSE;
}
return S_OK; return S_OK;
} }
@ -836,7 +908,8 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Reset(IEnumMoniker *iface)
TRACE("(%p)->()\n", iface); TRACE("(%p)->()\n", iface);
This->index = 0; This->sw_index = 0;
This->cm_index = 0;
return S_OK; return S_OK;
} }
@ -862,24 +935,33 @@ static const IEnumMonikerVtbl IEnumMoniker_Vtbl =
DEVENUM_IEnumMoniker_Clone DEVENUM_IEnumMoniker_Clone
}; };
HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, HKEY special_hkey, IEnumMoniker ** ppEnumMoniker) HRESULT create_EnumMoniker(REFCLSID class, IEnumMoniker **ppEnumMoniker)
{ {
EnumMonikerImpl * pEnumMoniker = CoTaskMemAlloc(sizeof(EnumMonikerImpl)); EnumMonikerImpl * pEnumMoniker = CoTaskMemAlloc(sizeof(EnumMonikerImpl));
WCHAR buffer[78];
if (!pEnumMoniker) if (!pEnumMoniker)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
pEnumMoniker->IEnumMoniker_iface.lpVtbl = &IEnumMoniker_Vtbl; pEnumMoniker->IEnumMoniker_iface.lpVtbl = &IEnumMoniker_Vtbl;
pEnumMoniker->ref = 1; pEnumMoniker->ref = 1;
pEnumMoniker->index = 0; pEnumMoniker->sw_index = 0;
pEnumMoniker->hkey = hkey; pEnumMoniker->cm_index = 0;
pEnumMoniker->special_hkey = special_hkey; pEnumMoniker->class = *class;
strcpyW(buffer, clsidW);
StringFromGUID2(class, buffer + strlenW(buffer), CHARS_IN_GUID);
strcatW(buffer, instanceW);
if (RegOpenKeyExW(HKEY_CLASSES_ROOT, buffer, 0, KEY_ENUMERATE_SUB_KEYS, &pEnumMoniker->sw_key))
pEnumMoniker->sw_key = NULL;
strcpyW(buffer, wszActiveMovieKey);
StringFromGUID2(class, buffer + strlenW(buffer), CHARS_IN_GUID);
if (RegOpenKeyExW(HKEY_CURRENT_USER, buffer, 0, KEY_ENUMERATE_SUB_KEYS, &pEnumMoniker->cm_key))
pEnumMoniker->cm_key = NULL;
*ppEnumMoniker = &pEnumMoniker->IEnumMoniker_iface; *ppEnumMoniker = &pEnumMoniker->IEnumMoniker_iface;
if(RegQueryInfoKeyW(pEnumMoniker->hkey, NULL, NULL, NULL, &pEnumMoniker->subkey_cnt, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
pEnumMoniker->subkey_cnt = 0;
DEVENUM_LockModule(); DEVENUM_LockModule();
return S_OK; return S_OK;

View file

@ -76,69 +76,60 @@ static ULONG WINAPI DEVENUM_IParseDisplayName_Release(IParseDisplayName *iface)
* not in "@device:sw:{CLSID1}\<filter name or CLSID>" format * not in "@device:sw:{CLSID1}\<filter name or CLSID>" format
*/ */
static HRESULT WINAPI DEVENUM_IParseDisplayName_ParseDisplayName(IParseDisplayName *iface, static HRESULT WINAPI DEVENUM_IParseDisplayName_ParseDisplayName(IParseDisplayName *iface,
IBindCtx *pbc, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut) IBindCtx *pbc, LPOLESTR name, ULONG *eaten, IMoniker **ret)
{ {
LPOLESTR pszBetween = NULL; WCHAR buffer[MAX_PATH];
LPOLESTR pszClass = NULL; enum device_type type;
MediaCatMoniker * pMoniker = NULL; MediaCatMoniker *mon;
CLSID clsidDevice; CLSID class;
HRESULT res = S_OK;
WCHAR wszRegKeyName[MAX_PATH];
HKEY hbasekey;
int classlen;
static const WCHAR wszRegSeparator[] = {'\\', 0 };
TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(pszDisplayName), pchEaten, ppmkOut); TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(name), eaten, ret);
*ppmkOut = NULL; *ret = NULL;
if (pchEaten) if (eaten)
*pchEaten = strlenW(pszDisplayName); *eaten = strlenW(name);
pszDisplayName = strchrW(pszDisplayName, '{'); name = strchrW(name, ':') + 1;
pszBetween = strchrW(pszDisplayName, '}') + 2;
/* size = pszBetween - pszDisplayName - 1 (for '\\' after CLSID) if (name[0] == 's' && name[1] == 'w' && name[2] == ':')
* + 1 (for NULL character) {
*/ type = DEVICE_FILTER;
classlen = (int)(pszBetween - pszDisplayName - 1); name += 3;
pszClass = CoTaskMemAlloc((classlen + 1) * sizeof(WCHAR)); }
if (!pszClass) else if (name[0] == 'c' && name[1] == 'm' && name[2] == ':')
{
type = DEVICE_CODEC;
name += 3;
}
else
{
FIXME("unhandled device type %s\n", debugstr_w(name));
return MK_E_SYNTAX;
}
if (!(mon = DEVENUM_IMediaCatMoniker_Construct()))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
memcpy(pszClass, pszDisplayName, classlen * sizeof(WCHAR)); lstrcpynW(buffer, name, CHARS_IN_GUID);
pszClass[classlen] = 0; if (CLSIDFromString(buffer, &class) == S_OK)
TRACE("Device CLSID: %s\n", debugstr_w(pszClass));
res = CLSIDFromString(pszClass, &clsidDevice);
if (SUCCEEDED(res))
{ {
res = DEVENUM_GetCategoryKey(&clsidDevice, &hbasekey, wszRegKeyName, MAX_PATH); mon->has_class = TRUE;
mon->class = class;
name += CHARS_IN_GUID;
} }
if (SUCCEEDED(res)) mon->type = type;
if (!(mon->name = CoTaskMemAlloc((strlenW(name) + 1) * sizeof(WCHAR))))
{ {
pMoniker = DEVENUM_IMediaCatMoniker_Construct(); IMoniker_Release(&mon->IMoniker_iface);
if (pMoniker) return E_OUTOFMEMORY;
{
strcatW(wszRegKeyName, wszRegSeparator);
strcatW(wszRegKeyName, pszBetween);
if (RegCreateKeyW(hbasekey, wszRegKeyName, &pMoniker->hkey) == ERROR_SUCCESS)
*ppmkOut = &pMoniker->IMoniker_iface;
else
{
IMoniker_Release(&pMoniker->IMoniker_iface);
res = MK_E_NOOBJECT;
}
}
} }
strcpyW(mon->name, name);
CoTaskMemFree(pszClass); *ret = &mon->IMoniker_iface;
TRACE("-- returning: %x\n", res); return S_OK;
return res;
} }
/********************************************************************** /**********************************************************************

View file

@ -29,7 +29,7 @@ reactos/dll/directx/wine/d3drm # Synced to WineStaging-3.9
reactos/dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-3.9 reactos/dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-3.9
reactos/dll/directx/wine/d3dxof # Synced to WineStaging-3.3 reactos/dll/directx/wine/d3dxof # Synced to WineStaging-3.3
reactos/dll/directx/wine/ddraw # Synced to WineStaging-3.9 reactos/dll/directx/wine/ddraw # Synced to WineStaging-3.9
reactos/dll/directx/wine/devenum # Synced to WineStaging-3.3 reactos/dll/directx/wine/devenum # Synced to WineStaging-3.9
reactos/dll/directx/wine/dinput # Synced to WineStaging-3.3 reactos/dll/directx/wine/dinput # Synced to WineStaging-3.3
reactos/dll/directx/wine/dinput8 # Synced to WineStaging-3.3 reactos/dll/directx/wine/dinput8 # Synced to WineStaging-3.3
reactos/dll/directx/wine/dmusic # Synced to WineStaging-3.3 reactos/dll/directx/wine/dmusic # Synced to WineStaging-3.3