В общем так (результаты исследований):
ProgIdFromCLSID даёт результат только для объектов ActiveX, не ниже. Попросить систему разобрать по составу моникеры устройств нельзя, но их IMoniker::GetDisplayName вполне поддаётся осмыслению вручную (выделяем элементы, разделённые символами ':', '\\', '#', '{'..'}'). Тем не менее, есть "родной" способ проследить путь до устройства, который можно показывать пользователю (на человеческом языке).
допустим у нас есть моникер устройства IMoniker.
1. Получаем GUID моникера функцией IMoniker::GetClassID - это класс "устройства" ("device.1")
2. Создаём перечислитель классов CLSID_SystemDeviceEnum с интерфейсом ICreateDevEnum
3. Получаем набор моникеров IEnumMoniker при помощи ICreateDevEnum::CreateClassEnumerator, указав полученный от моникера GUID
4. перебираем моникеры в наборе, получая из GUID и рекурсивно повторяем шаг 2 до тех пор, пока один из моникеров не совпадёт с исходным моникером. Проверить это можно функцией IMoniker::IsEqual
таким образом, получается что нужно строить всю структуру классов полностью, независимо от того, хочу я узнать информацию про один класс, или про все
Строчку на человеческом языке, соответсвующую классу можно получить через интерфейс IPropertyBag. Имя свойства целиком совпадает с ключом в реестре, в разделе описывающем этот класс. Работает только для объектов, полученных при помощи CreateClassEnumerator. Гарантируется как минимум "FriendlyName", но я обнаружил у себя раздел, судя по классиду, соответсвующий устройствам захвата видео, но не имеющий человеческих опознавательных строчек.
А, да, ещё не все свойства имеют тип "строчка".