devenum: Enumerate both regular key and special key for special categories.
This commit is contained in:
parent
6ce17c1fa4
commit
92be7be48d
|
@ -37,7 +37,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(devenum);
|
|||
|
||||
extern HINSTANCE DEVENUM_hInstance;
|
||||
|
||||
const WCHAR wszInstanceKeyName[] ={'I','n','s','t','a','n','c','e',0};
|
||||
const WCHAR wszInstanceKeyName[] ={'\\','I','n','s','t','a','n','c','e',0};
|
||||
|
||||
static const WCHAR wszRegSeparator[] = {'\\', 0 };
|
||||
static const WCHAR wszActiveMovieKey[] = {'S','o','f','t','w','a','r','e','\\',
|
||||
|
@ -134,13 +134,57 @@ HRESULT DEVENUM_GetCategoryKey(REFCLSID clsidDeviceClass, HKEY *pBaseKey, WCHAR
|
|||
if (!StringFromGUID2(clsidDeviceClass, wszRegKeyName + CLSID_STR_LEN, maxLen - CLSID_STR_LEN))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
strcatW(wszRegKeyName, wszRegSeparator);
|
||||
strcatW(wszRegKeyName, wszInstanceKeyName);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HKEY open_category_key(const CLSID *clsid)
|
||||
{
|
||||
WCHAR key_name[sizeof(wszInstanceKeyName)/sizeof(WCHAR) + CHARS_IN_GUID-1 + 6 /* strlen("CLSID\") */], *ptr;
|
||||
HKEY ret;
|
||||
|
||||
strcpyW(key_name, clsid_keyname);
|
||||
ptr = key_name + strlenW(key_name);
|
||||
*ptr++ = '\\';
|
||||
|
||||
if (!StringFromGUID2(clsid, ptr, CHARS_IN_GUID))
|
||||
return NULL;
|
||||
|
||||
ptr += strlenW(ptr);
|
||||
strcpyW(ptr, wszInstanceKeyName);
|
||||
|
||||
if (RegOpenKeyExW(HKEY_CLASSES_ROOT, key_name, 0, KEY_READ, &ret) != ERROR_SUCCESS) {
|
||||
WARN("Could not open %s\n", debugstr_w(key_name));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static HKEY open_special_category_key(const CLSID *clsid, BOOL create)
|
||||
{
|
||||
WCHAR key_name[sizeof(wszActiveMovieKey)/sizeof(WCHAR) + CHARS_IN_GUID-1];
|
||||
HKEY ret;
|
||||
LONG res;
|
||||
|
||||
strcpyW(key_name, wszActiveMovieKey);
|
||||
if (!StringFromGUID2(clsid, key_name + sizeof(wszActiveMovieKey)/sizeof(WCHAR)-1, CHARS_IN_GUID))
|
||||
return NULL;
|
||||
|
||||
if(create)
|
||||
res = RegCreateKeyW(HKEY_CURRENT_USER, key_name, &ret);
|
||||
else
|
||||
res = RegOpenKeyExW(HKEY_CURRENT_USER, key_name, 0, KEY_READ, &ret);
|
||||
if (res != ERROR_SUCCESS) {
|
||||
WARN("Could not open %s\n", debugstr_w(key_name));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void DEVENUM_ReadPinTypes(HKEY hkeyPinKey, REGFILTERPINS *rgPin)
|
||||
{
|
||||
HKEY hkeyTypes = NULL;
|
||||
|
@ -466,9 +510,7 @@ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
|
|||
IEnumMoniker **ppEnumMoniker,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
WCHAR wszRegKey[MAX_PATH];
|
||||
HKEY hkey;
|
||||
HKEY hbasekey;
|
||||
HKEY hkey, special_hkey = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p)->(%s, %p, %x)\n", iface, debugstr_guid(clsidDeviceClass), ppEnumMoniker, dwFlags);
|
||||
|
@ -483,29 +525,29 @@ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
|
|||
DEVENUM_RegisterLegacyAmFilters();
|
||||
}
|
||||
|
||||
hr = DEVENUM_GetCategoryKey(clsidDeviceClass, &hbasekey, wszRegKey, MAX_PATH);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (IsSpecialCategory(clsidDeviceClass))
|
||||
{
|
||||
hr = DEVENUM_CreateSpecialCategories();
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
if (RegOpenKeyW(hbasekey, wszRegKey, &hkey) != ERROR_SUCCESS)
|
||||
|
||||
special_hkey = open_special_category_key(clsidDeviceClass, FALSE);
|
||||
if (!special_hkey)
|
||||
{
|
||||
ERR("Couldn't open registry key for special device: %s\n",
|
||||
debugstr_guid(clsidDeviceClass));
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
else if (RegOpenKeyW(hbasekey, wszRegKey, &hkey) != ERROR_SUCCESS)
|
||||
|
||||
hkey = open_category_key(clsidDeviceClass);
|
||||
if (!hkey && !special_hkey)
|
||||
{
|
||||
FIXME("Category %s not found\n", debugstr_guid(clsidDeviceClass));
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
return DEVENUM_IEnumMoniker_Construct(hkey, ppEnumMoniker);
|
||||
return DEVENUM_IEnumMoniker_Construct(hkey, special_hkey, ppEnumMoniker);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
|
|
|
@ -68,7 +68,7 @@ typedef struct
|
|||
} MediaCatMoniker;
|
||||
|
||||
MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void) DECLSPEC_HIDDEN;
|
||||
HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker) DECLSPEC_HIDDEN;
|
||||
HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, HKEY special_hkey, IEnumMoniker ** ppEnumMoniker) DECLSPEC_HIDDEN;
|
||||
|
||||
extern ClassFactoryImpl DEVENUM_ClassFactory DECLSPEC_HIDDEN;
|
||||
extern ICreateDevEnum DEVENUM_CreateDevEnum DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -35,7 +35,9 @@ typedef struct
|
|||
IEnumMoniker IEnumMoniker_iface;
|
||||
LONG ref;
|
||||
DWORD index;
|
||||
DWORD subkey_cnt;
|
||||
HKEY hkey;
|
||||
HKEY special_hkey;
|
||||
} EnumMonikerImpl;
|
||||
|
||||
typedef struct
|
||||
|
@ -717,6 +719,8 @@ static ULONG WINAPI DEVENUM_IEnumMoniker_Release(IEnumMoniker *iface)
|
|||
|
||||
if (!ref)
|
||||
{
|
||||
if(This->special_hkey)
|
||||
RegCloseKey(This->special_hkey);
|
||||
RegCloseKey(This->hkey);
|
||||
CoTaskMemFree(This);
|
||||
DEVENUM_UnlockModule();
|
||||
|
@ -738,7 +742,12 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(IEnumMoniker *iface, ULONG celt,
|
|||
|
||||
while (fetched < celt)
|
||||
{
|
||||
res = RegEnumKeyW(This->hkey, This->index, buffer, sizeof(buffer) / sizeof(WCHAR));
|
||||
if(This->index+fetched < This->subkey_cnt)
|
||||
res = RegEnumKeyW(This->hkey, This->index+fetched, buffer, sizeof(buffer) / sizeof(WCHAR));
|
||||
else if(This->special_hkey)
|
||||
res = RegEnumKeyW(This->special_hkey, This->index+fetched-This->subkey_cnt, buffer, sizeof(buffer) / sizeof(WCHAR));
|
||||
else
|
||||
break;
|
||||
if (res != ERROR_SUCCESS)
|
||||
{
|
||||
break;
|
||||
|
@ -747,7 +756,8 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(IEnumMoniker *iface, ULONG celt,
|
|||
if (!pMoniker)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
if (RegOpenKeyW(This->hkey, buffer, &pMoniker->hkey) != ERROR_SUCCESS)
|
||||
if (RegOpenKeyW(This->index+fetched < This->subkey_cnt ? This->hkey : This->special_hkey,
|
||||
buffer, &pMoniker->hkey) != ERROR_SUCCESS)
|
||||
{
|
||||
IMoniker_Release(&pMoniker->IMoniker_iface);
|
||||
break;
|
||||
|
@ -772,17 +782,16 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(IEnumMoniker *iface, ULONG celt,
|
|||
static HRESULT WINAPI DEVENUM_IEnumMoniker_Skip(IEnumMoniker *iface, ULONG celt)
|
||||
{
|
||||
EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
|
||||
DWORD subKeys;
|
||||
DWORD special_subkeys = 0;
|
||||
|
||||
TRACE("(%p)->(%d)\n", iface, celt);
|
||||
|
||||
/* Before incrementing, check if there are any more values to run through.
|
||||
Some programs use the Skip() function to get the number of devices */
|
||||
if(RegQueryInfoKeyW(This->hkey, NULL, NULL, NULL, &subKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
if((This->index + celt) >= subKeys)
|
||||
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;
|
||||
}
|
||||
|
@ -824,7 +833,7 @@ static const IEnumMonikerVtbl IEnumMoniker_Vtbl =
|
|||
DEVENUM_IEnumMoniker_Clone
|
||||
};
|
||||
|
||||
HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker)
|
||||
HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, HKEY special_hkey, IEnumMoniker ** ppEnumMoniker)
|
||||
{
|
||||
EnumMonikerImpl * pEnumMoniker = CoTaskMemAlloc(sizeof(EnumMonikerImpl));
|
||||
if (!pEnumMoniker)
|
||||
|
@ -834,9 +843,14 @@ HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker)
|
|||
pEnumMoniker->ref = 1;
|
||||
pEnumMoniker->index = 0;
|
||||
pEnumMoniker->hkey = hkey;
|
||||
pEnumMoniker->special_hkey = special_hkey;
|
||||
|
||||
*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();
|
||||
|
||||
return S_OK;
|
||||
|
|
Loading…
Reference in New Issue