reactos/lib/devenum
diff -N createdevenum.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ createdevenum.c 20 Dec 2004 22:09:31 -0000 1.1
@@ -0,0 +1,437 @@
+/*
+ * ICreateDevEnum implementation for DEVENUM.dll
+ *
+ * Copyright (C) 2002 Robert Shearman
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * NOTES ON THIS FILE:
+ * - Implements ICreateDevEnum interface which creates an IEnumMoniker
+ * implementation
+ * - Also creates the special registry keys created at run-time
+ */
+
+#define NONAMELESSSTRUCT
+#define NONAMELESSUNION
+
+
+#define DUMMYSTRUCTNAME s
+#define DUMMYSTRUCTNAME1 s1
+#define DUMMYSTRUCTNAME2 s2
+#define DUMMYSTRUCTNAME3 s3
+#define DUMMYSTRUCTNAME4 s4
+#define DUMMYSTRUCTNAME5 s5
+
+#define DUMMYUNIONNAME u
+#define DUMMYUNIONNAME1 u1
+#define DUMMYUNIONNAME2 u2
+#define DUMMYUNIONNAME3 u3
+#define DUMMYUNIONNAME4 u4
+#define DUMMYUNIONNAME5 u5
+#define DUMMYUNIONNAME6 u6
+#define DUMMYUNIONNAME7 u7
+#define DUMMYUNIONNAME8 u8
+
+#include "devenum_private.h"
+
+#include "wine/debug.h"
+#include "mmddk.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(devenum);
+
+extern HINSTANCE DEVENUM_hInstance;
+
+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','\\',
+ 'M','i','c','r','o','s','o','f','t','\\',
+ 'A','c','t','i','v','e','M','o','v','i','e','\\',
+ 'd','e','v','e','n','u','m','\\',0};
+
+static ULONG WINAPI DEVENUM_ICreateDevEnum_AddRef(ICreateDevEnum * iface);
+static HRESULT DEVENUM_CreateSpecialCategories(void);
+
+/**********************************************************************
+ * DEVENUM_ICreateDevEnum_QueryInterface (also IUnknown)
+ */
+static HRESULT WINAPI DEVENUM_ICreateDevEnum_QueryInterface(
+ ICreateDevEnum * iface,
+ REFIID riid,
+ LPVOID *ppvObj)
+{
+ TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+
+ if (ppvObj == NULL) return E_POINTER;
+
+ if (IsEqualGUID(riid, &IID_IUnknown) ||
+ IsEqualGUID(riid, &IID_ICreateDevEnum))
+ {
+ *ppvObj = (LPVOID)iface;
+ DEVENUM_ICreateDevEnum_AddRef(iface);
+ return S_OK;
+ }
+
+ FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+}
+
+/**********************************************************************
+ * DEVENUM_ICreateDevEnum_AddRef (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_ICreateDevEnum_AddRef(ICreateDevEnum * iface)
+{
+ TRACE("\n");
+
+ DEVENUM_LockModule();
+
+ return 2; /* non-heap based object */
+}
+
+/**********************************************************************
+ * DEVENUM_ICreateDevEnum_Release (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_ICreateDevEnum_Release(ICreateDevEnum * iface)
+{
+ TRACE("\n");
+
+ DEVENUM_UnlockModule();
+
+ return 1; /* non-heap based object */
+}
+
+/**********************************************************************
+ * DEVENUM_ICreateDevEnum_CreateClassEnumerator
+ */
+HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
+ ICreateDevEnum * iface,
+ REFCLSID clsidDeviceClass,
+ IEnumMoniker **ppEnumMoniker,
+ DWORD dwFlags)
+{
+ WCHAR wszRegKey[MAX_PATH];
+ HKEY hkey;
+ HKEY hbasekey;
+ CreateDevEnumImpl *This = (CreateDevEnumImpl *)iface;
+
+ TRACE("(%p)->(%s, %p, %lx)\n\tDeviceClass:\t%s\n", This, debugstr_guid(clsidDeviceClass), ppEnumMoniker, dwFlags, debugstr_guid(clsidDeviceClass));
+
+ if (!ppEnumMoniker)
+ return E_POINTER;
+
+ *ppEnumMoniker = NULL;
+
+ if (IsEqualGUID(clsidDeviceClass, &CLSID_AudioRendererCategory) ||
+ IsEqualGUID(clsidDeviceClass, &CLSID_AudioInputDeviceCategory) ||
+ IsEqualGUID(clsidDeviceClass, &CLSID_MidiRendererCategory))
+ {
+ hbasekey = HKEY_CURRENT_USER;
+ strcpyW(wszRegKey, wszActiveMovieKey);
+
+ if (!StringFromGUID2(clsidDeviceClass, wszRegKey + strlenW(wszRegKey), MAX_PATH - strlenW(wszRegKey)))
+ return E_OUTOFMEMORY;
+ }
+ else
+ {
+ hbasekey = HKEY_CLASSES_ROOT;
+ strcpyW(wszRegKey, clsid_keyname);
+ strcatW(wszRegKey, wszRegSeparator);
+
+ if (!StringFromGUID2(clsidDeviceClass, wszRegKey + CLSID_STR_LEN, MAX_PATH - CLSID_STR_LEN))
+ return E_OUTOFMEMORY;
+
+ strcatW(wszRegKey, wszRegSeparator);
+ strcatW(wszRegKey, wszInstanceKeyName);
+ }
+
+ if (RegOpenKeyW(hbasekey, wszRegKey, &hkey) != ERROR_SUCCESS)
+ {
+ if (IsEqualGUID(clsidDeviceClass, &CLSID_AudioRendererCategory) ||
+ IsEqualGUID(clsidDeviceClass, &CLSID_AudioInputDeviceCategory) ||
+ IsEqualGUID(clsidDeviceClass, &CLSID_MidiRendererCategory))
+ {
+ HRESULT hr = DEVENUM_CreateSpecialCategories();
+ if (FAILED(hr))
+ return hr;
+ if (RegOpenKeyW(hbasekey, wszRegKey, &hkey) != ERROR_SUCCESS)
+ {
+ ERR("Couldn't open registry key for special device: %s\n",
+ debugstr_guid(clsidDeviceClass));
+ return S_FALSE;
+ }
+ }
+ else
+ {
+ FIXME("Category %s not found\n", debugstr_guid(clsidDeviceClass));
+ return S_FALSE;
+ }
+ }
+
+ return DEVENUM_IEnumMoniker_Construct(hkey, ppEnumMoniker);
+}
+
+/**********************************************************************
+ * ICreateDevEnum_Vtbl
+ */
+static ICreateDevEnumVtbl ICreateDevEnum_Vtbl =
+{
+ DEVENUM_ICreateDevEnum_QueryInterface,
+ DEVENUM_ICreateDevEnum_AddRef,
+ DEVENUM_ICreateDevEnum_Release,
+ DEVENUM_ICreateDevEnum_CreateClassEnumerator,
+};
+
+/**********************************************************************
+ * static CreateDevEnum instance
+ */
+CreateDevEnumImpl DEVENUM_CreateDevEnum = { &ICreateDevEnum_Vtbl };
+
+/**********************************************************************
+ * DEVENUM_CreateAMCategoryKey (INTERNAL)
+ *
+ * Creates a registry key for a category at HKEY_CURRENT_USER\Software\
+ * Microsoft\ActiveMovie\devenum\{clsid}
+ */
+static HRESULT DEVENUM_CreateAMCategoryKey(const CLSID * clsidCategory)
+{
+ WCHAR wszRegKey[MAX_PATH];
+ HRESULT res = S_OK;
+ HKEY hkeyDummy = NULL;
+
+ strcpyW(wszRegKey, wszActiveMovieKey);
+
+ if (!StringFromGUID2(clsidCategory, wszRegKey + strlenW(wszRegKey), sizeof(wszRegKey)/sizeof(wszRegKey[0]) - strlenW(wszRegKey)))
+ res = E_INVALIDARG;
+
+ if (SUCCEEDED(res))
+ res = HRESULT_FROM_WIN32(
+ RegCreateKeyW(HKEY_CURRENT_USER, wszRegKey, &hkeyDummy));
+
+ if (hkeyDummy)
+ RegCloseKey(hkeyDummy);
+
+ if (FAILED(res))
+ ERR("Failed to create key HKEY_CURRENT_USER\\%s\n", debugstr_w(wszRegKey));
+
+ return res;
+}
+
+/**********************************************************************
+ * DEVENUM_CreateSpecialCategories (INTERNAL)
+ *
+ * Creates the keys in the registry for the dynamic categories
+ */
+static HRESULT DEVENUM_CreateSpecialCategories()
+{
+ HRESULT res;
+ WCHAR szDSoundNameFormat[MAX_PATH + 1];
+ WCHAR szDSoundName[MAX_PATH + 1];
+ DWORD iDefaultDevice = -1;
+ UINT numDevs;
+ IFilterMapper2 * pMapper = NULL;
+ REGFILTER2 rf2;
+ REGFILTERPINS2 rfp2;
+
+ rf2.dwVersion = 2;
+ rf2.dwMerit = MERIT_PREFERRED;
+ rf2.u.s1.cPins2 = 1;
+ rf2.u.s1.rgPins2 = &rfp2;
+ rfp2.dwFlags = REG_PINFLAG_B_RENDERER;
+ rfp2.cInstances = 1;
+ rfp2.nMediums = 0;
+ rfp2.lpMedium = NULL;
+ rfp2.clsPinCategory = &IID_NULL;
+
+ if (!LoadStringW(DEVENUM_hInstance, IDS_DEVENUM_DS, szDSoundNameFormat, sizeof(szDSoundNameFormat)/sizeof(szDSoundNameFormat[0])-1))
+ {
+ ERR("Couldn't get string resource (GetLastError() is %ld)\n", GetLastError());
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ res = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC,
+ &IID_IFilterMapper2, (void **) &pMapper);
+ /*
+ * Fill in info for devices
+ */
+ if (SUCCEEDED(res))
+ {
+ UINT i;
+ WAVEOUTCAPSW wocaps;
+ WAVEINCAPSW wicaps;
+ MIDIOUTCAPSW mocaps;
+ REGPINTYPES * pTypes;
+
+ numDevs = waveOutGetNumDevs();
+
+ res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
+ if (FAILED(res)) /* can't register any devices in this category */
+ numDevs = 0;
+
+ for (i = 0; i < numDevs; i++)
+ {
+ if (waveOutGetDevCapsW(i, &wocaps, sizeof(WAVEOUTCAPSW))
+ == MMSYSERR_NOERROR)
+ {
+ IMoniker * pMoniker = NULL;
+
+ rfp2.nMediaTypes = 1;
+ pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES));
+ if (!pTypes)
+ {
+ IFilterMapper2_Release(pMapper);
+ return E_OUTOFMEMORY;
+ }
+ /* FIXME: Native devenum seems to register a lot more types for
+ * DSound than we do. Not sure what purpose they serve */
+ pTypes[0].clsMajorType = &MEDIATYPE_Audio;
+ pTypes[0].clsMinorType = &MEDIASUBTYPE_PCM;
+
+ rfp2.lpMediaType = pTypes;
+
+ res = IFilterMapper2_RegisterFilter(pMapper,
+ &CLSID_AudioRender,
+ wocaps.szPname,
+ &pMoniker,
+ &CLSID_AudioRendererCategory,
+ wocaps.szPname,
+ &rf2);
+
+ /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */
+
+ if (pMoniker)
+ IMoniker_Release(pMoniker);
+
+ wsprintfW(szDSoundName, szDSoundNameFormat, wocaps.szPname);
+ res = IFilterMapper2_RegisterFilter(pMapper,
+ &CLSID_DSoundRender,
+ szDSoundName,
+ &pMoniker,
+ &CLSID_AudioRendererCategory,
+ szDSoundName,
+ &rf2);
+
+ /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */
+
+ if (pMoniker)
+ IMoniker_Release(pMoniker);
+
+ if (i == iDefaultDevice)
+ {
+ FIXME("Default device\n");
+ }
+
+ CoTaskMemFree(pTypes);
+ }
+ }
+
+ numDevs = waveInGetNumDevs();
+
+ res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioInputDeviceCategory);
+ if (FAILED(res)) /* can't register any devices in this category */
+ numDevs = 0;
+
+ for (i = 0; i < numDevs; i++)
+ {
+ if (waveInGetDevCapsW(i, &wicaps, sizeof(WAVEINCAPSW))
+ == MMSYSERR_NOERROR)
+ {
+ IMoniker * pMoniker = NULL;
+
+ rfp2.nMediaTypes = 1;
+ pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES));
+ if (!pTypes)
+ {
+ IFilterMapper2_Release(pMapper);
+ return E_OUTOFMEMORY;
+ }
+
+ /* FIXME: Not sure if these are correct */
+ pTypes[0].clsMajorType = &MEDIATYPE_Audio;
+ pTypes[0].clsMinorType = &MEDIASUBTYPE_PCM;
+
+ rfp2.lpMediaType = pTypes;
+
+ res = IFilterMapper2_RegisterFilter(pMapper,
+ &CLSID_AudioRecord,
+ wicaps.szPname,
+ &pMoniker,
+ &CLSID_AudioInputDeviceCategory,
+ wicaps.szPname,
+ &rf2);
+
+ /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */
+
+ if (pMoniker)
+ IMoniker_Release(pMoniker);
+
+ CoTaskMemFree(pTypes);
+ }
+ }
+
+ numDevs = midiOutGetNumDevs();
+
+ res = DEVENUM_CreateAMCategoryKey(&CLSID_MidiRendererCategory);
+ if (FAILED(res)) /* can't register any devices in this category */
+ numDevs = 0;
+
+ for (i = 0; i < numDevs; i++)
+ {
+ if (midiOutGetDevCapsW(i, &mocaps, sizeof(MIDIOUTCAPSW))
+ == MMSYSERR_NOERROR)
+ {
+ IMoniker * pMoniker = NULL;
+
+ rfp2.nMediaTypes = 1;
+ pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES));
+ if (!pTypes)
+ {
+ IFilterMapper2_Release(pMapper);
+ return E_OUTOFMEMORY;
+ }
+
+ /* FIXME: Not sure if these are correct */
+ pTypes[0].clsMajorType = &MEDIATYPE_Midi;
+ pTypes[0].clsMinorType = &MEDIASUBTYPE_None;
+
+ rfp2.lpMediaType = pTypes;
+
+ res = IFilterMapper2_RegisterFilter(pMapper,
+ &CLSID_AVIMIDIRender,
+ mocaps.szPname,
+ &pMoniker,
+ &CLSID_MidiRendererCategory,
+ mocaps.szPname,
+ &rf2);
+
+ /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */
+ /* Native version sets MidiOutId */
+
+ if (pMoniker)
+ IMoniker_Release(pMoniker);
+
+ if (i == iDefaultDevice)
+ {
+ FIXME("Default device\n");
+ }
+
+ CoTaskMemFree(pTypes);
+ }
+ }
+ }
+
+ if (pMapper)
+ IFilterMapper2_Release(pMapper);
+ return res;
+}
reactos/lib/devenum
diff -N devenum_main.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ devenum_main.c 20 Dec 2004 22:09:31 -0000 1.1
@@ -0,0 +1,389 @@
+/*
+ * exported dll functions for devenum.dll
+ *
+ * Copyright (C) 2002 John K. Hohm
+ * Copyright (C) 2002 Robert Shearman
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "devenum_private.h"
+#include "wine/debug.h"
+#include "winreg.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(devenum);
+
+LONG dll_refs;
+HINSTANCE DEVENUM_hInstance;
+
+typedef struct
+{
+ REFCLSID clsid;
+ LPCWSTR friendly_name;
+ BOOL instance;
+} register_info;
+
+static HRESULT register_clsids(int count, const register_info * pRegInfo, LPCWSTR pszThreadingModel);
+static void DEVENUM_RegisterQuartz(void);
+
+/***********************************************************************
+ * Global string constant definitions
+ */
+const WCHAR clsid_keyname[6] = { 'C', 'L', 'S', 'I', 'D', 0 };
+
+/***********************************************************************
+ * DllEntryPoint
+ */
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
+{
+ TRACE("%p 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad);
+
+ switch(fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ DEVENUM_hInstance = hinstDLL;
+ DisableThreadLibraryCalls(hinstDLL);
+ break;
+
+ case DLL_PROCESS_DETACH:
+ DEVENUM_hInstance = 0;
+ break;
+ }
+ return TRUE;
+}
+
+/***********************************************************************
+ * DllGetClassObject (DEVENUM.@)
+ */
+HRESULT WINAPI DEVENUM_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
+{
+ TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv);
+
+ *ppv = NULL;
+
+ /* FIXME: we should really have two class factories.
+ * Oh well - works just fine as it is */
+ if (IsEqualGUID(rclsid, &CLSID_SystemDeviceEnum) ||
+ IsEqualGUID(rclsid, &CLSID_CDeviceMoniker))
+ return IClassFactory_QueryInterface((IClassFactory*)&DEVENUM_ClassFactory, iid, ppv);
+
+ FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+/***********************************************************************
+ * DllCanUnloadNow (DEVENUM.@)
+ */
+HRESULT WINAPI DEVENUM_DllCanUnloadNow(void)
+{
+ return dll_refs != 0 ? S_FALSE : S_OK;
+}
+
+/***********************************************************************
+ * DllRegisterServer (DEVENUM.@)
+ */
+HRESULT WINAPI DEVENUM_DllRegisterServer(void)
+{
+ HRESULT res;
+ HKEY hkeyClsid = NULL;
+ HKEY hkey1 = NULL;
+ HKEY hkey2 = NULL;
+ LPOLESTR pszClsidDevMon = NULL;
+ IFilterMapper2 * pMapper = NULL;
+ LPVOID mapvptr;
+ static const WCHAR threadingModel[] = {'B','o','t','h',0};
+ static const WCHAR sysdevenum[] = {'S','y','s','t','e','m',' ','D','e','v','i','c','e',' ','E','n','u','m',0};
+ static const WCHAR devmon[] = {'D','e','v','i','c','e','M','o','n','i','k','e','r',0};
+ static const WCHAR acmcat[] = {'A','C','M',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0};
+ static const WCHAR vidcat[] = {'I','C','M',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0};
+ static const WCHAR filtcat[] = {'A','c','t','i','v','e','M','o','v','i','e',' ','F','i','l','t','e','r',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0};
+ static const WCHAR vfwcat[] = {'V','F','W',' ','C','a','p','t','u','r','e',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0};
+ static const WCHAR wavein[] = {'W','a','v','e','I','n',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r', 0};
+ static const WCHAR waveout[] = {'W','a','v','e','O','u','t',' ','a','n','d',' ','D','S','o','u','n','d',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0};
+ static const WCHAR midiout[] = {'M','i','d','i','O','u','t',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0};
+ static const WCHAR amcat[] = {'A','c','t','i','v','e','M','o','v','i','e',' ','F','i','l','t','e','r',' ','C','a','t','e','g','o','r','i','e','s',0};
+ static const WCHAR device[] = {'d','e','v','i','c','e',0};
+ static const WCHAR device_1[] = {'d','e','v','i','c','e','.','1',0};
+ static const register_info ri[] =
+ {
+ {&CLSID_SystemDeviceEnum, sysdevenum, FALSE},
+ {&CLSID_CDeviceMoniker, devmon, FALSE},
+ {&CLSID_AudioCompressorCategory, acmcat, TRUE},
+ {&CLSID_VideoCompressorCategory, vidcat, TRUE},
+ {&CLSID_LegacyAmFilterCategory, filtcat, TRUE},
+ {&CLSID_VideoInputDeviceCategory, vfwcat, FALSE},
+ {&CLSID_AudioInputDeviceCategory, wavein, FALSE},
+ {&CLSID_AudioRendererCategory, waveout, FALSE},
+ {&CLSID_MidiRendererCategory, midiout, FALSE},
+ {&CLSID_ActiveMovieCategories, amcat, TRUE}
+ };
+
+ TRACE("\n");
+
+ res = register_clsids(sizeof(ri) / sizeof(register_info), ri, threadingModel);
+
+ /* Quartz is needed for IFilterMapper2 */
+ DEVENUM_RegisterQuartz();
+
+/*** ActiveMovieFilter Categories ***/
+
+ CoInitialize(NULL);
+
+ res = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC,
+ &IID_IFilterMapper2, &mapvptr);
+ if (SUCCEEDED(res))
+ {
+ static const WCHAR friendlyvidcap[] = {'V','i','d','e','o',' ','C','a','p','t','u','r','e',' ','S','o','u','r','c','e','s',0};
+ static const WCHAR friendlydshow[] = {'D','i','r','e','c','t','S','h','o','w',' ','F','i','l','t','e','r','s',0};
+ static const WCHAR friendlyvidcomp[] = {'V','i','d','e','o',' ','C','o','m','p','r','e','s','s','o','r','s',0};
+ static const WCHAR friendlyaudcap[] = {'A','u','d','i','o',' ','C','a','p','t','u','r','e',' ','S','o','u','r','c','e','s',0};
+ static const WCHAR friendlyaudcomp[] = {'A','u','d','i','o',' ','C','o','m','p','r','e','s','s','o','r','s',0};
+ static const WCHAR friendlyaudrend[] = {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r','s',0};
+ static const WCHAR friendlymidirend[] = {'M','i','d','i',' ','R','e','n','d','e','r','e','r','s',0};
+ static const WCHAR friendlyextrend[] = {'E','x','t','e','r','n','a','l',' ','R','e','n','d','e','r','e','r','s',0};
+ static const WCHAR friendlydevctrl[] = {'D','e','v','i','c','e',' ','C','o','n','t','r','o','l',' ','F','i','l','t','e','r','s',0};
+
+ pMapper = (IFilterMapper2*)mapvptr;
+
+ IFilterMapper2_CreateCategory(pMapper, &CLSID_VideoInputDeviceCategory, MERIT_DO_NOT_USE, friendlyvidcap);
+ IFilterMapper2_CreateCategory(pMapper, &CLSID_LegacyAmFilterCategory, MERIT_NORMAL, friendlydshow);
+ IFilterMapper2_CreateCategory(pMapper, &CLSID_VideoCompressorCategory, MERIT_DO_NOT_USE, friendlyvidcomp);
+ IFilterMapper2_CreateCategory(pMapper, &CLSID_AudioInputDeviceCategory, MERIT_DO_NOT_USE, friendlyaudcap);
+ IFilterMapper2_CreateCategory(pMapper, &CLSID_AudioCompressorCategory, MERIT_DO_NOT_USE, friendlyaudcomp);
+ IFilterMapper2_CreateCategory(pMapper, &CLSID_AudioRendererCategory, MERIT_NORMAL, friendlyaudrend);
+ IFilterMapper2_CreateCategory(pMapper, &CLSID_MidiRendererCategory, MERIT_NORMAL, friendlymidirend);
+ IFilterMapper2_CreateCategory(pMapper, &CLSID_TransmitCategory, MERIT_DO_NOT_USE, friendlyextrend);
+ IFilterMapper2_CreateCategory(pMapper, &CLSID_DeviceControlCategory, MERIT_DO_NOT_USE, friendlydevctrl);
+
+ IFilterMapper2_Release(pMapper);
+ }
+
+/*** CDeviceMoniker ***/
+ if (SUCCEEDED(res))
+ {
+ res = StringFromCLSID(&CLSID_CDeviceMoniker, &pszClsidDevMon);
+ }
+ if (SUCCEEDED(res))
+ {
+ res = RegOpenKeyW(HKEY_CLASSES_ROOT, clsid_keyname, &hkeyClsid)
+ == ERROR_SUCCESS ? S_OK : E_FAIL;
+ }
+ if (SUCCEEDED(res))
+ {
+ res = RegOpenKeyW(hkeyClsid, pszClsidDevMon, &hkey1)
+ == ERROR_SUCCESS ? S_OK : E_FAIL;
+ }
+ if (SUCCEEDED(res))
+ {
+ static const WCHAR wszProgID[] = {'P','r','o','g','I','D',0};
+ res = RegCreateKeyW(hkey1, wszProgID, &hkey2)
+ == ERROR_SUCCESS ? S_OK : E_FAIL;
+ }
+ if (SUCCEEDED(res))
+ {
+ res = RegSetValueW(hkey2, NULL, REG_SZ, device_1, (lstrlenW(device_1) + 1) * sizeof(WCHAR))
+ == ERROR_SUCCESS ? S_OK : E_FAIL;
+ }
+
+ if (hkey2)
+ {
+ RegCloseKey(hkey2);
+ hkey2 = NULL;
+ }
+
+ if (SUCCEEDED(res))
+ {
+ static const WCHAR wszVProgID[] = {'V','e','r','s','i','o','n','I','n','d','e','p','e','d','e','n','t','P','r','o','g','I','D',0};
+ res = RegCreateKeyW(hkey1, wszVProgID, &hkey2)
+ == ERROR_SUCCESS ? S_OK : E_FAIL;
+ }
+ if (SUCCEEDED(res))
+ {
+ res = RegSetValueW(hkey2, NULL, REG_SZ, device, (lstrlenW(device) + 1) * sizeof(WCHAR))
+ == ERROR_SUCCESS ? S_OK : E_FAIL;
+ }
+
+ if (hkey2)
+ {
+ RegCloseKey(hkey2);
+ hkey2 = NULL;
+ }
+
+ if (hkey1)
+ {
+ RegCloseKey(hkey1);
+ hkey1 = NULL;
+ }
+
+ if (SUCCEEDED(res))
+ {
+ res = RegCreateKeyW(HKEY_CLASSES_ROOT, device, &hkey1)
+ == ERROR_SUCCESS ? S_OK : E_FAIL;
+ }
+ if (SUCCEEDED(res))
+ {
+ res = RegCreateKeyW(hkey1, clsid_keyname, &hkey2)
+ == ERROR_SUCCESS ? S_OK : E_FAIL;
+ }
+ if (SUCCEEDED(res))
+ {
+ res = RegSetValueW(hkey2, NULL, REG_SZ, pszClsidDevMon, (lstrlenW(pszClsidDevMon) + 1) * sizeof(WCHAR))
+ == ERROR_SUCCESS ? S_OK : E_FAIL;
+ }
+ if (hkey2)
+ {
+ RegCloseKey(hkey2);
+ hkey2 = NULL;
+ }
+
+ if (hkey1)
+ {
+ RegCloseKey(hkey1);
+ hkey1 = NULL;
+ }
+
+ if (SUCCEEDED(res))
+ {
+ res = RegCreateKeyW(HKEY_CLASSES_ROOT, device_1, &hkey1)
+ == ERROR_SUCCESS ? S_OK : E_FAIL;
+ }
+ if (SUCCEEDED(res))
+ {
+ res = RegCreateKeyW(hkey1, clsid_keyname, &hkey2)
+ == ERROR_SUCCESS ? S_OK : E_FAIL;
+ }
+ if (SUCCEEDED(res))
+ {
+ res = RegSetValueW(hkey2, NULL, REG_SZ, pszClsidDevMon, (lstrlenW(pszClsidDevMon) + 1) * sizeof(WCHAR))
+ == ERROR_SUCCESS ? S_OK : E_FAIL;
+ }
+
+ if (hkey2)
+ RegCloseKey(hkey2);
+
+ if (hkey1)
+ RegCloseKey(hkey1);
+
+ if (hkeyClsid)
+ RegCloseKey(hkeyClsid);
+
+ if (pszClsidDevMon)
+ CoTaskMemFree(pszClsidDevMon);
+
+ CoUninitialize();
+
+ return res;
+}
+
+/***********************************************************************
+ * DllUnregisterServer (DEVENUM.@)
+ */
+HRESULT WINAPI DEVENUM_DllUnregisterServer(void)
+{
+ FIXME("stub!\n");
+ return E_FAIL;
+}
+
+static HRESULT register_clsids(int count, const register_info * pRegInfo, LPCWSTR pszThreadingModel)
+{
+ HRESULT res = S_OK;
+ WCHAR dll_module[MAX_PATH];
+ LPOLESTR clsidString;
+ HKEY hkeyClsid;
+ HKEY hkeySub;
+ HKEY hkeyInproc32;
+ HKEY hkeyInstance = NULL;
+ int i;
+ static const WCHAR wcszInproc32[] = {'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
+ static const WCHAR wcszThreadingModel[] = {'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
+
+ res = RegOpenKeyW(HKEY_CLASSES_ROOT, clsid_keyname, &hkeyClsid)
+ == ERROR_SUCCESS ? S_OK : E_FAIL;
+
+ TRACE("HModule = %p\n", DEVENUM_hInstance);
+ i = GetModuleFileNameW(DEVENUM_hInstance, dll_module,
+ sizeof(dll_module) / sizeof(WCHAR));
+ if (!i)
+ return HRESULT_FROM_WIN32(GetLastError());
+ if (i >= sizeof(dll_module) / sizeof(WCHAR))
+ return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+
+ for (i = 0; i < count; i++)
+ {
+ if (SUCCEEDED(res))
+ {
+ res = StringFromCLSID(pRegInfo[i].clsid, &clsidString);
+ }
+ if (SUCCEEDED(res))
+ {
+ res = RegCreateKeyW(hkeyClsid, clsidString, &hkeySub)
+ == ERROR_SUCCESS ? S_OK : E_FAIL;
+ }
+ if (pRegInfo[i].instance && SUCCEEDED(res))
+ {
+ res = RegCreateKeyW(hkeySub, wszInstanceKeyName, &hkeyInstance)
+ == ERROR_SUCCESS ? S_OK : E_FAIL;
+ RegCloseKey(hkeyInstance);
+ }
+ if (SUCCEEDED(res))
+ {
+ RegSetValueW(hkeySub,
+ NULL,
+ REG_SZ,
+ pRegInfo->friendly_name ? pRegInfo[i].friendly_name : clsidString,
+ (lstrlenW(pRegInfo[i].friendly_name ? pRegInfo->friendly_name : clsidString) + 1) * sizeof(WCHAR));
+ res = RegCreateKeyW(hkeySub, wcszInproc32, &hkeyInproc32)
+ == ERROR_SUCCESS ? S_OK : E_FAIL;
+ }
+ if (SUCCEEDED(res))
+ {
+ RegSetValueW(hkeyInproc32,
+ NULL,
+ REG_SZ,
+ dll_module,
+ (lstrlenW(dll_module) + 1) * sizeof(WCHAR));
+ RegSetValueExW(hkeyInproc32,
+ wcszThreadingModel,
+ 0,
+ REG_SZ,
+ (LPCVOID)pszThreadingModel,
+ (lstrlenW(pszThreadingModel) + 1) * sizeof(WCHAR));
+ RegCloseKey(hkeyInproc32);
+ }
+ RegCloseKey(hkeySub);
+ CoTaskMemFree(clsidString);
+ clsidString = NULL;
+ }
+
+ RegCloseKey(hkeyClsid);
+
+ return res;
+}
+
+typedef HRESULT (WINAPI *DllRegisterServer_func)(void);
+
+/* calls DllRegisterServer() for the Quartz DLL */
+static void DEVENUM_RegisterQuartz()
+{
+ HANDLE hDLL = LoadLibraryA("quartz.dll");
+ DllRegisterServer_func pDllRegisterServer = NULL;
+ if (hDLL)
+ pDllRegisterServer = (DllRegisterServer_func)GetProcAddress(hDLL, "DllRegisterServer");
+ if (pDllRegisterServer)
+ {
+ HRESULT hr = pDllRegisterServer();
+ if (FAILED(hr))
+ ERR("Failed to register Quartz. Error was 0x%lx)\n", hr);
+ }
+}
reactos/lib/devenum
diff -N mediacatenum.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ mediacatenum.c 20 Dec 2004 22:09:31 -0000 1.1
@@ -0,0 +1,848 @@
+/*
+ * IEnumMoniker implementation for DEVENUM.dll
+ *
+ * Copyright (C) 2002 Robert Shearman
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * NOTES ON THIS FILE:
+ * - Implements IEnumMoniker interface which enumerates through moniker
+ * objects created from HKEY_CLASSES/CLSID/{DEVICE_CLSID}/Instance
+ */
+
+#include "devenum_private.h"
+#include "vfwmsgs.h"
+#include "oleauto.h"
+
+#include "wine/debug.h"
+
+
+/* #define ICOM_THIS_From_IROTData(class, name) class* This = (class*)(((char*)name)-sizeof(void*)) */
+
+WINE_DEFAULT_DEBUG_CHANNEL(devenum);
+
+static ULONG WINAPI DEVENUM_IEnumMoniker_AddRef(LPENUMMONIKER iface);
+static ULONG WINAPI DEVENUM_IMediaCatMoniker_AddRef(LPMONIKER iface);
+static ULONG WINAPI DEVENUM_IPropertyBag_AddRef(LPPROPERTYBAG iface);
+
+typedef struct
+{
+ IPropertyBagVtbl *lpVtbl;
+ DWORD ref;
+ HKEY hkey;
+} RegPropBagImpl;
+
+
+static HRESULT WINAPI DEVENUM_IPropertyBag_QueryInterface(
+ LPPROPERTYBAG iface,
+ REFIID riid,
+ LPVOID *ppvObj)
+{
+ RegPropBagImpl *This = (RegPropBagImpl *)iface;
+ TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+
+ if (This == NULL || ppvObj == NULL) return E_POINTER;
+
+ if (IsEqualGUID(riid, &IID_IUnknown) ||
+ IsEqualGUID(riid, &IID_IPropertyBag))
+ {
+ *ppvObj = (LPVOID)iface;
+ DEVENUM_IPropertyBag_AddRef(iface);
+ return S_OK;
+ }
+
+ FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+}
+
+/**********************************************************************
+ * DEVENUM_IPropertyBag_AddRef (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_IPropertyBag_AddRef(LPPROPERTYBAG iface)
+{
+ RegPropBagImpl *This = (RegPropBagImpl *)iface;
+ TRACE("\n");
+
+ return InterlockedIncrement(&This->ref);
+}
+
+/**********************************************************************
+ * DEVENUM_IPropertyBag_Release (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_IPropertyBag_Release(LPPROPERTYBAG iface)
+{
+ RegPropBagImpl *This = (RegPropBagImpl *)iface;
+
+ TRACE("\n");
+
+ if (InterlockedDecrement(&This->ref) == 0) {
+ RegCloseKey(This->hkey);
+ CoTaskMemFree(This);
+ DEVENUM_UnlockModule();
+ return 0;
+ }
+ return This->ref;
+}
+
+static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
+ LPPROPERTYBAG iface,
+ LPCOLESTR pszPropName,
+ VARIANT* pVar,
+ IErrorLog* pErrorLog)
+{
+ LPVOID pData = NULL;
+ LONG received;
+ DWORD type = 0;
+ RegPropBagImpl *This = (RegPropBagImpl *)iface;
+ HRESULT res = S_OK;
+ LONG reswin32;
+
+ TRACE("(%p)->(%s, %p, %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog);
+
+ if (!pszPropName || !pVar)
+ return E_POINTER;
+
+ reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, NULL, NULL, &received);
+ res = HRESULT_FROM_WIN32(reswin32);
+
+ if (SUCCEEDED(res))
+ {
+ pData = HeapAlloc(GetProcessHeap(), 0, received);
+
+ /* 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);
+ res = HRESULT_FROM_WIN32(reswin32);
+ }
+
+ if (SUCCEEDED(res))
+ {
+ res = E_INVALIDARG; /* assume we cannot coerce into right type */
+
+ TRACE("Read %ld bytes (%s)\n", received, type == REG_SZ ? debugstr_w((LPWSTR)pData) : "binary data");
+
+ switch (type)
+ {
+ case REG_SZ:
+ switch (V_VT(pVar))
+ {
+ case VT_LPWSTR:
+ V_UNION(pVar, bstrVal) = CoTaskMemAlloc(received);
+ memcpy(V_UNION(pVar, bstrVal), (LPWSTR)pData, received);
+ res = S_OK;
+ break;
+ case VT_EMPTY:
+ V_VT(pVar) = VT_BSTR;
+ /* fall through */
+ case VT_BSTR:
+ V_UNION(pVar, bstrVal) = SysAllocStringLen((LPWSTR)pData, received/sizeof(WCHAR) - 1);
+ res = S_OK;
+ break;
+ }
+ break;
+ case REG_DWORD:
+ TRACE("REG_DWORD: %lx\n", *(DWORD *)pData);
+ switch (V_VT(pVar))
+ {
+ case VT_EMPTY:
+ V_VT(pVar) = VT_I4;
+ /* fall through */
+ case VT_I4:
+ case VT_UI4:
+ V_UNION(pVar, ulVal) = *(DWORD *)pData;
+ res = S_OK;
+ break;
+ }
+ break;
+ case REG_BINARY:
+ {
+ SAFEARRAYBOUND bound;
+ void * pArrayElements;
+ bound.lLbound = 0;
+ bound.cElements = received;
+ TRACE("REG_BINARY: len = %ld\n", received);
+ switch (V_VT(pVar))
+ {
+ case VT_EMPTY:
+ case VT_ARRAY | VT_UI1:
+ if (!(V_UNION(pVar, parray) = SafeArrayCreate(VT_UI1, 1, &bound)))
+ res = E_OUTOFMEMORY;
+ res = S_OK;
+ break;
+ }
+
+ if (res == E_INVALIDARG)
+ break;
+
+ res = SafeArrayAccessData(V_UNION(pVar, parray), &pArrayElements);
+ if (FAILED(res))
+ break;
+
+ CopyMemory(pArrayElements, pData, received);
+ res = SafeArrayUnaccessData(V_UNION(pVar, parray));
+ break;
+ }
+ }
+ if (res == E_INVALIDARG)
+ FIXME("Variant type %x not supported for regtype %lx\n", V_VT(pVar), type);
+ }
+
+ if (pData)
+ HeapFree(GetProcessHeap(), 0, pData);
+
+ TRACE("<- %lx\n", res);
+ return res;
+}
+
+static HRESULT WINAPI DEVENUM_IPropertyBag_Write(
+ LPPROPERTYBAG iface,
+ LPCOLESTR pszPropName,
+ VARIANT* pVar)
+{
+ RegPropBagImpl *This = (RegPropBagImpl *)iface;
+ LPVOID lpData = NULL;
+ DWORD cbData = 0;
+ DWORD dwType = 0;
+ HRESULT res = S_OK;
+
+ TRACE("(%p)->(%s, %p)\n", This, debugstr_w(pszPropName), pVar);
+
+ switch (V_VT(pVar))
+ {
+ case VT_BSTR:
+ TRACE("writing %s\n", debugstr_w(V_UNION(pVar, bstrVal)));
+ lpData = (LPVOID)V_UNION(pVar, bstrVal);
+ dwType = REG_SZ;
+ cbData = (lstrlenW(V_UNION(pVar, bstrVal)) + 1) * sizeof(WCHAR);
+ break;
+ case VT_I4:
+ case VT_UI4:
+ TRACE("writing %lu\n", V_UNION(pVar, ulVal));
+ lpData = (LPVOID)&V_UNION(pVar, ulVal);
+ dwType = REG_DWORD;
+ cbData = sizeof(DWORD);
+ break;
+ case VT_ARRAY | VT_UI1:
+ {
+ LONG lUbound = 0;
+ LONG lLbound = 0;
+ dwType = REG_BINARY;
+ res = SafeArrayGetLBound(V_UNION(pVar, parray), 1, &lLbound);
+ res = SafeArrayGetUBound(V_UNION(pVar, parray), 1, &lUbound);
+ cbData = (lUbound - lLbound + 1) /* * sizeof(BYTE)*/;
+ TRACE("cbData: %ld\n", cbData);
+ res = SafeArrayAccessData(V_UNION(pVar, parray), &lpData);
+ break;
+ }
+ default:
+ FIXME("Variant type %d not handled\n", V_VT(pVar));
+ return E_FAIL;
+ }
+
+ if (RegSetValueExW(This->hkey,
+ pszPropName, 0,
+ dwType, lpData, cbData) != ERROR_SUCCESS)
+ res = E_FAIL;
+
+ if (V_VT(pVar) & VT_ARRAY)
+ res = SafeArrayUnaccessData(V_UNION(pVar, parray));
+
+ return res;
+}
+
+static IPropertyBagVtbl IPropertyBag_Vtbl =
+{
+ DEVENUM_IPropertyBag_QueryInterface,
+ DEVENUM_IPropertyBag_AddRef,
+ DEVENUM_IPropertyBag_Release,
+ DEVENUM_IPropertyBag_Read,
+ DEVENUM_IPropertyBag_Write
+};
+
+static HRESULT DEVENUM_IPropertyBag_Construct(HANDLE hkey, IPropertyBag **ppBag)
+{
+ RegPropBagImpl * rpb = CoTaskMemAlloc(sizeof(RegPropBagImpl));
+ if (!rpb)
+ return E_OUTOFMEMORY;
+ rpb->lpVtbl = &IPropertyBag_Vtbl;
+ rpb->ref = 1;
+ rpb->hkey = hkey;
+ *ppBag = (IPropertyBag*)rpb;
+ DEVENUM_LockModule();
+ return S_OK;
+}
+
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_QueryInterface(
+ LPMONIKER iface,
+ REFIID riid,
+ LPVOID *ppvObj)
+{
+ MediaCatMoniker *This = (MediaCatMoniker *)iface;
+ TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+
+ if (This == NULL || ppvObj == NULL) return E_POINTER;
+
+ *ppvObj = NULL;
+
+ if (IsEqualGUID(riid, &IID_IUnknown) ||
+ IsEqualGUID(riid, &IID_IPersist) ||
+ IsEqualGUID(riid, &IID_IPersistStream) ||
+ IsEqualGUID(riid, &IID_IMoniker))
+ {
+ *ppvObj = (LPVOID)iface;
+ DEVENUM_IMediaCatMoniker_AddRef(iface);
+ return S_OK;
+ }
+
+ FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+}
+
+/**********************************************************************
+ * DEVENUM_IMediaCatMoniker_AddRef (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_IMediaCatMoniker_AddRef(LPMONIKER iface)
+{
+ MediaCatMoniker *This = (MediaCatMoniker *)iface;
+ TRACE("\n");
+
+ return InterlockedIncrement(&This->ref);
+}
+
+/**********************************************************************
+ * DEVENUM_IMediaCatMoniker_Release (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_IMediaCatMoniker_Release(LPMONIKER iface)
+{
+ MediaCatMoniker *This = (MediaCatMoniker *)iface;
+ ULONG ref;
+ TRACE("\n");
+
+ ref = InterlockedDecrement(&This->ref);
+ if (ref == 0) {
+ RegCloseKey(This->hkey);
+ CoTaskMemFree(This);
+ DEVENUM_UnlockModule();
+ }
+ return ref;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetClassID(
+ LPMONIKER iface,
+ CLSID* pClassID)
+{
+ MediaCatMoniker *This = (MediaCatMoniker *)iface;
+ FIXME("(%p)->(%p)\n", This, pClassID);
+
+ if (pClassID == NULL)
+ return E_POINTER;
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_IsDirty(LPMONIKER iface)
+{
+ FIXME("()\n");
+
+ return S_FALSE;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Load(LPMONIKER iface, IStream* pStm)
+{
+ FIXME("(%p)\n", pStm);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Save(LPMONIKER iface, IStream* pStm, BOOL fClearDirty)
+{
+ FIXME("(%p, %s)\n", pStm, fClearDirty ? "true" : "false");
+
+ return STG_E_CANTSAVE;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetSizeMax(
+ LPMONIKER iface,
+ ULARGE_INTEGER* pcbSize)
+{
+ FIXME("(%p)\n", pcbSize);
+
+ ZeroMemory(pcbSize, sizeof(*pcbSize));
+
+ return S_OK;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToObject(
+ LPMONIKER iface,
+ IBindCtx* pbc,
+ IMoniker* pmkToLeft,
+ REFIID riidResult,
+ void** ppvResult)
+{
+ IUnknown * pObj = NULL;
+ IPropertyBag * pProp = NULL;
+ CLSID clsID;
+ VARIANT var;
+ HRESULT res = E_FAIL;
+
+ MediaCatMoniker *This = (MediaCatMoniker *)iface;
+
+ VariantClear(&var);
+
+ TRACE("(%p)->(%p, %p, %s, %p)\n", This, pbc, pmkToLeft, debugstr_guid(riidResult), ppvResult);
+
+ *ppvResult = NULL;
+
+ if(pmkToLeft==NULL)
+ {
+ /* first activation of this class */
+ LPVOID pvptr;
+ res=IMoniker_BindToStorage(iface, NULL, NULL, &IID_IPropertyBag, &pvptr);
+ pProp = (IPropertyBag*)pvptr;
+ if (SUCCEEDED(res))
+ {
+ V_VT(&var) = VT_LPWSTR;
+ res = IPropertyBag_Read(pProp, clsid_keyname, &var, NULL);
+ }
+ if (SUCCEEDED(res))
+ {
+ res = CLSIDFromString(V_UNION(&var,bstrVal), &clsID);
+ CoTaskMemFree(V_UNION(&var, bstrVal));
+ }
+ if (SUCCEEDED(res))
+ {
+ res=CoCreateInstance(&clsID,NULL,CLSCTX_ALL,&IID_IUnknown,&pvptr);
+ pObj = (IUnknown*)pvptr;
+ }
+ }
+
+ if (pObj!=NULL)
+ {
+ /* get the requested interface from the loaded class */
+ res= IUnknown_QueryInterface(pObj,riidResult,ppvResult);
+ }
+
+ if (pProp)
+ {
+ IPropertyBag_Release(pProp);
+ }
+
+ TRACE("<- 0x%lx\n", res);
+
+ return res;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToStorage(
+ LPMONIKER iface,
+ IBindCtx* pbc,
+ IMoniker* pmkToLeft,
+ REFIID riid,
+ void** ppvObj)
+{
+ MediaCatMoniker *This = (MediaCatMoniker *)iface;
+ TRACE("(%p)->(%p, %p, %s, %p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppvObj);
+
+ *ppvObj = NULL;
+
+ if (pbc || pmkToLeft)
+ return MK_E_NOSTORAGE;
+
+ if (IsEqualGUID(riid, &IID_IPropertyBag))
+ {
+ HANDLE hkey;
+ DuplicateHandle(GetCurrentProcess(), This->hkey, GetCurrentProcess(), &hkey, 0, 0, DUPLICATE_SAME_ACCESS);
+ return DEVENUM_IPropertyBag_Construct(hkey, (IPropertyBag**)ppvObj);
+ }
+
+ return MK_E_NOSTORAGE;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Reduce(
+ LPMONIKER iface,
+ IBindCtx* pbc,
+ DWORD dwReduceHowFar,
+ IMoniker** ppmkToLeft,
+ IMoniker** ppmkReduced)
+{
+ TRACE("(%p, %ld, %p, %p)\n", pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced);
+
+ if (ppmkToLeft)
+ *ppmkToLeft = NULL;
+ *ppmkReduced = iface;
+
+ return MK_S_REDUCED_TO_SELF;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_ComposeWith(
+ LPMONIKER iface,
+ IMoniker* pmkRight,
+ BOOL fOnlyIfNotGeneric,
+ IMoniker** ppmkComposite)
+{
+ FIXME("(%p, %s, %p): stub\n", pmkRight, fOnlyIfNotGeneric ? "true" : "false", ppmkComposite);
+
+ /* FIXME: use CreateGenericComposite? */
+ *ppmkComposite = NULL;
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Enum(
+ LPMONIKER iface,
+ BOOL fForward,
+ IEnumMoniker** ppenumMoniker)
+{
+ FIXME("(%s, %p): stub\n", fForward ? "true" : "false", ppenumMoniker);
+
+ *ppenumMoniker = NULL;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_IsEqual(
+ LPMONIKER iface,
+ IMoniker* pmkOtherMoniker)
+{
+ FIXME("(%p)\n", pmkOtherMoniker);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Hash(
+ LPMONIKER iface,
+ DWORD* pdwHash)
+{
+ TRACE("(%p)\n", pdwHash);
+
+ *pdwHash = 0;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_IsRunning(
+ LPMONIKER iface,
+ IBindCtx* pbc,
+ IMoniker* pmkToLeft,
+ IMoniker* pmkNewlyRunning)
+{
+ FIXME("(%p, %p, %p)\n", pbc, pmkToLeft, pmkNewlyRunning);
+
+ return S_FALSE;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetTimeOfLastChange(
+ LPMONIKER iface,
+ IBindCtx* pbc,
+ IMoniker* pmkToLeft,
+ FILETIME* pFileTime)
+{
+ TRACE("(%p, %p, %p)\n", pbc, pmkToLeft, pFileTime);
+
+ pFileTime->dwLowDateTime = 0xFFFFFFFF;
+ pFileTime->dwHighDateTime = 0x7FFFFFFF;
+
+ return MK_E_UNAVAILABLE;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_Inverse(
+ LPMONIKER iface,
+ IMoniker** ppmk)
+{
+ TRACE("(%p)\n", ppmk);
+
+ *ppmk = NULL;
+
+ return MK_E_NOINVERSE;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_CommonPrefixWith(
+ LPMONIKER iface,
+ IMoniker* pmkOtherMoniker,
+ IMoniker** ppmkPrefix)
+{
+ TRACE("(%p, %p)\n", pmkOtherMoniker, ppmkPrefix);
+
+ *ppmkPrefix = NULL;
+
+ return MK_E_NOPREFIX;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_RelativePathTo(
+ LPMONIKER iface,
+ IMoniker* pmkOther,
+ IMoniker** ppmkRelPath)
+{
+ TRACE("(%p, %p)\n", pmkOther, ppmkRelPath);
+
+ *ppmkRelPath = pmkOther;
+
+ return MK_S_HIM;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetDisplayName(
+ LPMONIKER iface,
+ IBindCtx* pbc,
+ IMoniker* pmkToLeft,
+ LPOLESTR* ppszDisplayName)
+{
+ MediaCatMoniker *This = (MediaCatMoniker *)iface;
+ WCHAR wszBuffer[MAX_PATH];
+ static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
+ LONG received = sizeof(wszFriendlyName);
+
+ TRACE("(%p, %p, %p)\n", pbc, pmkToLeft, ppszDisplayName);
+
+ *ppszDisplayName = NULL;
+
+ /* FIXME: should this be the weird stuff we have to parse in IParseDisplayName? */
+ if (RegQueryValueW(This->hkey, wszFriendlyName, wszBuffer, &received) == ERROR_SUCCESS)
+ {
+ *ppszDisplayName = CoTaskMemAlloc(received);
+ strcpyW(*ppszDisplayName, wszBuffer);
+ return S_OK;
+ }
+
+ return E_FAIL;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_ParseDisplayName(
+ LPMONIKER iface,
+ IBindCtx* pbc,
+ IMoniker* pmkToLeft,
+ LPOLESTR pszDisplayName,
+ ULONG* pchEaten,
+ IMoniker** ppmkOut)
+{
+ FIXME("(%p, %p, %s, %p, %p)\n", pbc, pmkToLeft, debugstr_w(pszDisplayName), pchEaten, ppmkOut);
+
+ *pchEaten = 0;
+ *ppmkOut = NULL;
+
+ return MK_E_SYNTAX;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_IsSystemMoniker(
+ LPMONIKER iface,
+ DWORD* pdwMksys)
+{
+ TRACE("(%p)\n", pdwMksys);
+
+ return S_FALSE;
+}
+
+static IMonikerVtbl IMoniker_Vtbl =
+{
+ DEVENUM_IMediaCatMoniker_QueryInterface,
+ DEVENUM_IMediaCatMoniker_AddRef,
+ DEVENUM_IMediaCatMoniker_Release,
+ DEVENUM_IMediaCatMoniker_GetClassID,
+ DEVENUM_IMediaCatMoniker_IsDirty,
+ DEVENUM_IMediaCatMoniker_Load,
+ DEVENUM_IMediaCatMoniker_Save,
+ DEVENUM_IMediaCatMoniker_GetSizeMax,
+ DEVENUM_IMediaCatMoniker_BindToObject,
+ DEVENUM_IMediaCatMoniker_BindToStorage,
+ DEVENUM_IMediaCatMoniker_Reduce,
+ DEVENUM_IMediaCatMoniker_ComposeWith,
+ DEVENUM_IMediaCatMoniker_Enum,
+ DEVENUM_IMediaCatMoniker_IsEqual,
+ DEVENUM_IMediaCatMoniker_Hash,
+ DEVENUM_IMediaCatMoniker_IsRunning,
+ DEVENUM_IMediaCatMoniker_GetTimeOfLastChange,
+ DEVENUM_IMediaCatMoniker_Inverse,
+ DEVENUM_IMediaCatMoniker_CommonPrefixWith,
+ DEVENUM_IMediaCatMoniker_RelativePathTo,
+ DEVENUM_IMediaCatMoniker_GetDisplayName,
+ DEVENUM_IMediaCatMoniker_ParseDisplayName,
+ DEVENUM_IMediaCatMoniker_IsSystemMoniker
+};
+
+MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct()
+{
+ MediaCatMoniker * pMoniker = NULL;
+ pMoniker = CoTaskMemAlloc(sizeof(MediaCatMoniker));
+ if (!pMoniker)
+ return NULL;
+
+ pMoniker->lpVtbl = &IMoniker_Vtbl;
+ pMoniker->ref = 0;
+ pMoniker->hkey = NULL;
+
+ DEVENUM_IMediaCatMoniker_AddRef((LPMONIKER)pMoniker);
+
+ DEVENUM_LockModule();
+
+ return pMoniker;
+}
+
+/**********************************************************************
+ * DEVENUM_IEnumMoniker_QueryInterface (also IUnknown)
+ */
+static HRESULT WINAPI DEVENUM_IEnumMoniker_QueryInterface(
+ LPENUMMONIKER iface,
+ REFIID riid,
+ LPVOID *ppvObj)
+{
+ EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
+ TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+
+ if (This == NULL || ppvObj == NULL) return E_POINTER;
+
+ if (IsEqualGUID(riid, &IID_IUnknown) ||
+ IsEqualGUID(riid, &IID_IEnumMoniker))
+ {
+ *ppvObj = (LPVOID)iface;
+ DEVENUM_IEnumMoniker_AddRef(iface);
+ return S_OK;
+ }
+
+ FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+}
+
+/**********************************************************************
+ * DEVENUM_IEnumMoniker_AddRef (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_IEnumMoniker_AddRef(LPENUMMONIKER iface)
+{
+ EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
+
+ TRACE("\n");
+
+ return InterlockedIncrement(&This->ref);
+}
+
+/**********************************************************************
+ * DEVENUM_IEnumMoniker_Release (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_IEnumMoniker_Release(LPENUMMONIKER iface)
+{
+ EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
+
+ TRACE("\n");
+
+ if (!InterlockedDecrement(&This->ref))
+ {
+ RegCloseKey(This->hkey);
+ CoTaskMemFree(This);
+ DEVENUM_UnlockModule();
+ return 0;
+ }
+ return This->ref;
+}
+
+static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(LPENUMMONIKER iface, ULONG celt, IMoniker ** rgelt, ULONG * pceltFetched)
+{
+ WCHAR buffer[MAX_PATH + 1];
+ LONG res;
+ ULONG fetched = 0;
+ MediaCatMoniker * pMoniker;
+ EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
+
+ TRACE("(%ld, %p, %p)\n", celt, rgelt, pceltFetched);
+
+ while (fetched < celt)
+ {
+ res = RegEnumKeyW(This->hkey, This->index, buffer, sizeof(buffer) / sizeof(WCHAR));
+ if (res != ERROR_SUCCESS)
+ {
+ break;
+ }
+ pMoniker = DEVENUM_IMediaCatMoniker_Construct();
+ if (!pMoniker)
+ return E_OUTOFMEMORY;
+
+ if (RegOpenKeyW(This->hkey, buffer, &pMoniker->hkey) != ERROR_SUCCESS)
+ {
+ DEVENUM_IMediaCatMoniker_Release((LPMONIKER)pMoniker);
+ break;
+ }
+ rgelt[fetched] = (LPMONIKER)pMoniker;
+ fetched++;
+ }
+
+ This->index += fetched;
+
+ TRACE("-- fetched %ld\n", fetched);
+
+ if (pceltFetched)
+ *pceltFetched = fetched;
+
+ if (fetched != celt)
+ return S_FALSE;
+ else
+ return S_OK;
+}
+
+static HRESULT WINAPI DEVENUM_IEnumMoniker_Skip(LPENUMMONIKER iface, ULONG celt)
+{
+ EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
+
+ TRACE("(%ld)\n", celt);
+
+ This->index += celt;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI DEVENUM_IEnumMoniker_Reset(LPENUMMONIKER iface)
+{
+ EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
+
+ TRACE("()\n");
+
+ This->index = 0;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI DEVENUM_IEnumMoniker_Clone(LPENUMMONIKER iface, IEnumMoniker ** ppenum)
+{
+ FIXME("(%p): stub\n", ppenum);
+
+ return E_NOTIMPL;
+}
+
+/**********************************************************************
+ * IEnumMoniker_Vtbl
+ */
+static IEnumMonikerVtbl IEnumMoniker_Vtbl =
+{
+ DEVENUM_IEnumMoniker_QueryInterface,
+ DEVENUM_IEnumMoniker_AddRef,
+ DEVENUM_IEnumMoniker_Release,
+ DEVENUM_IEnumMoniker_Next,
+ DEVENUM_IEnumMoniker_Skip,
+ DEVENUM_IEnumMoniker_Reset,
+ DEVENUM_IEnumMoniker_Clone
+};
+
+HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker)
+{
+ EnumMonikerImpl * pEnumMoniker = CoTaskMemAlloc(sizeof(EnumMonikerImpl));
+ if (!pEnumMoniker)
+ return E_OUTOFMEMORY;
+
+ pEnumMoniker->lpVtbl = &IEnumMoniker_Vtbl;
+ pEnumMoniker->ref = 1;
+ pEnumMoniker->index = 0;
+ pEnumMoniker->hkey = hkey;
+
+ *ppEnumMoniker = (IEnumMoniker *)pEnumMoniker;
+
+ DEVENUM_LockModule();
+
+ return S_OK;
+}