Hi,
This patch implements the DevEnum DLL. It doesn't depend on DSHOW-02, but
does depend on DSHOW-01.
Changelog:
- Implement DevEnum DLL
Rob
diff -u -N -r -x *~ -x .#* -x CVS -x Makefile wine/dlls/devenum03/Makefile.in wine/dlls/devenum/Makefile.in
--- wine/dlls/devenum03/Makefile.in Fri May 17 04:37:12 2002
+++ wine/dlls/devenum/Makefile.in Mon Jun 30 00:27:21 2003
@@ -3,11 +3,19 @@
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = devenum.dll
+IMPORTS = kernel32 advapi32 ole32 oleaut32 winmm user32
+EXTRALIBS = $(LIBUUID)
LDDLLFLAGS = @LDDLLFLAGS@
SYMBOLFILE = $(MODULE).tmp.o
-C_SRCS = devenum_main.c
+C_SRCS = devenum_main.c \
+ factory.c \
+ createdevenum.c \
+ mediacatenum.c \
+ parsedisplayname.c
+
+RC_SRCS = devenum.rc
@MAKE_DLL_RULES@
diff -u -N -r -x *~ -x .#* -x CVS -x Makefile wine/dlls/devenum03/createdevenum.c wine/dlls/devenum/createdevenum.c
--- wine/dlls/devenum03/createdevenum.c Thu Jan 1 01:00:00 1970
+++ wine/dlls/devenum/createdevenum.c Mon Jun 23 16:51:32 2003
@@ -0,0 +1,378 @@
+/*
+ * 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
+ * - ...
+ */
+
+#include "devenum_private.h"
+
+#include "wine/debug.h"
+#include "mmddk.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(devenum);
+
+extern ICOM_VTABLE(IEnumMoniker) IEnumMoniker_Vtbl;
+
+extern HINSTANCE DEVENUM_hInstance;
+
+const WCHAR wszInstanceKeyName[] ={'I','n','s','t','a','n','c','e',0};
+const WCHAR wszRegSeperator[] = {'\\', 0 };
+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();
+
+/**********************************************************************
+ * DEVENUM_ICreateDevEnum_QueryInterface (also IUnknown)
+ */
+static HRESULT WINAPI DEVENUM_ICreateDevEnum_QueryInterface(
+ ICreateDevEnum * iface,
+ REFIID riid,
+ LPVOID *ppvObj)
+{
+ ICOM_THIS(CreateDevEnumImpl, 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_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)
+{
+ ICOM_THIS(CreateDevEnumImpl, iface);
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+
+ if (InterlockedIncrement(&This->ref) == 1) {
+ InterlockedIncrement(&dll_ref);
+ }
+ return This->ref;
+}
+
+/**********************************************************************
+ * DEVENUM_ICreateDevEnum_Release (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_ICreateDevEnum_Release(ICreateDevEnum * iface)
+{
+ ICOM_THIS(CreateDevEnumImpl, iface);
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+
+ if (InterlockedDecrement(&This->ref) == 0) {
+ InterlockedDecrement(&dll_ref);
+ }
+ return This->ref;
+}
+
+/**********************************************************************
+ * DEVENUM_ICreateDevEnum_CreateClassEnumerator
+ */
+HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
+ ICreateDevEnum * iface,
+ REFCLSID clsidDeviceClass,
+ IEnumMoniker **ppEnumMoniker,
+ DWORD dwFlags)
+{
+ WCHAR wszRegKey[MAX_PATH];
+ EnumMonikerImpl * pEnumMoniker;
+ HKEY hkey;
+ HKEY hbasekey;
+ ICOM_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_MidiRendererCategory))
+ {
+ if (FAILED(DEVENUM_CreateSpecialCategories()))
+ return E_FAIL;
+
+ 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, wszRegSeperator);
+
+ if (!StringFromGUID2(clsidDeviceClass, wszRegKey + CLSID_STR_LEN, MAX_PATH - CLSID_STR_LEN))
+ return E_OUTOFMEMORY;
+
+ strcatW(wszRegKey, wszRegSeperator);
+ strcatW(wszRegKey, wszInstanceKeyName);
+ }
+
+ if (RegOpenKeyW(hbasekey, wszRegKey, &hkey) != ERROR_SUCCESS)
+ {
+ FIXME("Category %s not found\n", debugstr_guid(clsidDeviceClass));
+ return S_FALSE;
+ }
+
+ pEnumMoniker = (EnumMonikerImpl *)CoTaskMemAlloc(sizeof(EnumMonikerImpl));
+ if (!pEnumMoniker)
+ return E_OUTOFMEMORY;
+
+ pEnumMoniker->lpVtbl = &IEnumMoniker_Vtbl;
+ pEnumMoniker->ref = 1;
+ pEnumMoniker->index = 0;
+ pEnumMoniker->hkey = hkey;
+
+ *ppEnumMoniker = (IEnumMoniker *)pEnumMoniker;
+
+ return S_OK;
+}
+
+/**********************************************************************
+ * ICreateDevEnum_Vtbl
+ */
+static ICOM_VTABLE(ICreateDevEnum) ICreateDevEnum_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ DEVENUM_ICreateDevEnum_QueryInterface,
+ DEVENUM_ICreateDevEnum_AddRef,
+ DEVENUM_ICreateDevEnum_Release,
+ DEVENUM_ICreateDevEnum_CreateClassEnumerator,
+};
+
+/**********************************************************************
+ * static CreateDevEnum instance
+ */
+CreateDevEnumImpl DEVENUM_CreateDevEnum = { &ICreateDevEnum_Vtbl, 0 };
+
+
+/**********************************************************************
+ * CreateSpecialCategories (INTERNAL)
+ *
+ * Creates the keys in the registry for the dynamic categories
+ */
+static HRESULT DEVENUM_CreateSpecialCategories()
+{
+ HRESULT res = S_OK;
+/* this section below needs some attention - when it is enabled it appears to create
+ * a circular dependency. IE IFilterMapper2_RegisterFilter calls back into this library
+ * which again calls RegisterFilter.
+ */
+#if 0
+ IMoniker * pMoniker = NULL;
+ WCHAR szAltNameFormat[MAX_PATH + 1];
+ WCHAR szAltName[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;
+
+ res = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC,
+ &IID_IFilterMapper2, (void **) &pMapper);
+ /*
+ * Fill in info for out devices
+ */
+ if (SUCCEEDED(res))
+ {
+ UINT i;
+ WAVEOUTCAPSW wocaps;
+ WAVEINCAPSW wicaps;
+ MIDIOUTCAPSW mocaps;
+ REGPINTYPES * pTypes;
+ numDevs = waveOutGetNumDevs();
+
+ for (i = 0; i < numDevs; i++)
+ {
+ LoadStringW(DEVENUM_hInstance, IDS_DEVENUM_DS, szAltNameFormat, MAX_PATH);
+ if (waveOutGetDevCapsW(i, &wocaps, sizeof(WAVEOUTCAPSW))
+ == MMSYSERR_NOERROR)
+ {
+ 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;
+
+ 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(szAltName, szAltNameFormat, wocaps.szPname);
+ IFilterMapper2_RegisterFilter(pMapper,
+ &CLSID_DSoundRender,
+ szAltName,
+ &pMoniker,
+ &CLSID_AudioRendererCategory,
+ szAltName,
+ &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();
+
+ for (i = 0; i < numDevs; i++)
+ {
+ if (waveInGetDevCapsW(i, &wicaps, sizeof(WAVEINCAPSW))
+ == MMSYSERR_NOERROR)
+ {
+ 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;
+
+ 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();
+
+ for (i = 0; i < numDevs; i++)
+ {
+ if (midiOutGetDevCapsW(i, &mocaps, sizeof(MIDIOUTCAPSW))
+ == MMSYSERR_NOERROR)
+ {
+ 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;
+
+ 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);
+#endif
+ return res;
+}
diff -u -N -r -x *~ -x .#* -x CVS -x Makefile wine/dlls/devenum03/devenum.rc wine/dlls/devenum/devenum.rc
--- wine/dlls/devenum03/devenum.rc Thu Jan 1 01:00:00 1970
+++ wine/dlls/devenum/devenum.rc Mon Jun 30 00:34:53 2003
@@ -0,0 +1,59 @@
+/*
+ * Resources for Device Enumerator
+ *
+ * Copyright 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 "winnls.h"
+
+LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
+
+STRINGTABLE DISCARDABLE
+{
+ 7 "Default DirectSound"
+ 8 "DirectSound: %s"
+ 9 "Default WaveOut Device"
+ 10 "Default MidiOut Device"
+}
+
+1 VERSIONINFO
+ FILEVERSION 6,3,1,881
+ PRODUCTVERSION 6,3,1,881
+ FILEFLAGSMASK 0x30003fL
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "04090000"
+ BEGIN
+ VALUE "CompanyName", "Wine Developer Team\000"
+ VALUE "FileDescription", "Wine Device Enumerator Library\000"
+ VALUE "FileVersion", "6.3.1.881\000"
+ VALUE "InternalName", "DEVENUM\000"
+ VALUE "LegalCopyright", "Copyright \251 2002\000"
+ VALUE "OriginalFilename", "DEVENUM.DLL\000"
+ VALUE "ProductName", "Wine\000"
+ VALUE "ProductVersion", "6.3.1.881\000"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 0
+ END
+END
diff -u -N -r -x *~ -x .#* -x CVS -x Makefile wine/dlls/devenum03/devenum.spec wine/dlls/devenum/devenum.spec
--- wine/dlls/devenum03/devenum.spec Thu Jan 2 17:55:45 2003
+++ wine/dlls/devenum/devenum.spec Tue Jan 7 17:24:24 2003
@@ -1,4 +1,4 @@
-@ stub DllCanUnloadNow
-@ stub DllGetClassObject
+@ stdcall DllCanUnloadNow() DEVENUM_DllCanUnloadNow
+@ stdcall DllGetClassObject(ptr ptr ptr) DEVENUM_DllGetClassObject
@ stdcall DllRegisterServer() DEVENUM_DllRegisterServer
-@ stub DllUnregisterServer
+@ stdcall DllUnregisterServer() DEVENUM_DllUnregisterServer
\ No newline at end of file
diff -u -N -r -x *~ -x .#* -x CVS -x Makefile wine/dlls/devenum03/devenum_main.c wine/dlls/devenum/devenum_main.c
--- wine/dlls/devenum03/devenum_main.c Thu Jan 2 17:55:45 2003
+++ wine/dlls/devenum/devenum_main.c Fri Jun 27 01:49:51 2003
@@ -1,12 +1,327 @@
+/*
+ * 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);
+DWORD dll_ref = 0;
+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);
+
+/***********************************************************************
+ * 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((LPCLASSFACTORY)&DEVENUM_ClassFactory, iid, ppv);
+ FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
+
/***********************************************************************
- * DllRegisterServer (DEVENUM.@)
+ * DllCanUnloadNow (DEVENUM.@)
+ */
+HRESULT WINAPI DEVENUM_DllCanUnloadNow()
+{
+ return dll_ref != 0 ? S_FALSE : S_OK;
+}
+
+/***********************************************************************
+ * DllRegisterServer (DEVENUM.@)
*/
HRESULT WINAPI DEVENUM_DllRegisterServer()
{
- FIXME("(): stub\n");
- return 0;
+ HRESULT res;
+ HKEY hkeyClsid = NULL;
+ HKEY hkey1 = NULL;
+ HKEY hkey2 = NULL;
+ LPOLESTR pszClsidDevMon = NULL;
+ IFilterMapper2 * pMapper = NULL;
+ const WCHAR threadingModel[] = {'B','o','t','h',0};
+ const WCHAR sysdevenum[] = {'S','y','s','t','e','m',' ','D','e','v','i','c','e',' ','E','n','u','m',0};
+ const WCHAR devmon[] = {'D','e','v','i','c','e','M','o','n','i','k','e','r',0};
+ const WCHAR acmcat[] = {'A','C','M',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0};
+ const WCHAR vidcat[] = {'I','C','M',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0};
+ 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};
+ 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};
+ const WCHAR wavein[] = {'W','a','v','e','I','n',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r', 0};
+ 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};
+ const WCHAR midiout[] = {'M','i','d','i','O','u','t',' ','C','l','a','s','s',' ','M','a','n','a','g','e','r',0};
+ 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};
+ const WCHAR device[] = {'d','e','v','i','c','e',0};
+ const WCHAR device_1[] = {'d','e','v','i','c','e','.','1',0};
+ 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);
+
+/*** ActiveMovieFilter Categories ***/
+ {
+ const WCHAR friendlyvidcap[] = {'V','i','d','e','o',' ','C','a','p','t','u','r','e',' ','S','o','u','r','c','e','s',0};
+ const WCHAR friendlydshow[] = {'D','i','r','e','c','t','S','h','o','w',' ','F','i','l','t','e','r','s',0};
+ const WCHAR friendlyvidcomp[] = {'V','i','d','e','o',' ','C','o','m','p','r','e','s','s','o','r','s',0};
+ const WCHAR friendlyaudcap[] = {'A','u','d','i','o',' ','C','a','p','t','u','r','e',' ','S','o','u','r','c','e','s',0};
+ const WCHAR friendlyaudcomp[] = {'A','u','d','i','o',' ','C','o','m','p','r','e','s','s','o','r','s',0};
+ const WCHAR friendlyaudrend[] = {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r','s',0};
+ const WCHAR friendlymidirend[] = {'M','i','d','i',' ','R','e','n','d','e','r','e','r','s',0};
+ const WCHAR friendlyextrend[] = {'E','x','t','e','r','n','a','l',' ','R','e','n','d','e','r','e','r','s',0};
+ const WCHAR friendlydevctrl[] = {'D','e','v','i','c','e',' ','C','o','n','t','r','o','l',' ','F','i','l','t','e','r','s',0};
+ CoInitialize(NULL);
+ res = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC,
+ &IID_IFilterMapper2, (void **) &pMapper);
+
+ 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);
+ CoUninitialize();
+ }
+
+/*** 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))
+ {
+ 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;
+ }
+ RegCloseKey(hkey2);
+ if (SUCCEEDED(res))
+ {
+ 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;
+ }
+ RegCloseKey(hkey2);
+ RegCloseKey(hkey1);
+ 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;
+ }
+ RegCloseKey(hkey2);
+ RegCloseKey(hkey1);
+
+ 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;
+ }
+ RegCloseKey(hkey2);
+ RegCloseKey(hkey1);
+
+ RegCloseKey(hkeyClsid);
+
+ if (pszClsidDevMon)
+ CoTaskMemFree(pszClsidDevMon);
+
+ return res;
+}
+
+/***********************************************************************
+ * DllUnregisterServer (DEVENUM.@)
+ */
+HRESULT WINAPI DEVENUM_DllUnregisterServer()
+{
+ 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;
+ const WCHAR wcszInproc32[] = {'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
+ 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);
+ if (!GetModuleFileNameW(DEVENUM_hInstance, dll_module,
+ sizeof(dll_module) / sizeof(WCHAR)))
+ return HRESULT_FROM_WIN32(GetLastError());
+
+ 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,
+ (LPVOID)pszThreadingModel,
+ (lstrlenW(pszThreadingModel) + 1) * sizeof(WCHAR));
+ RegCloseKey(hkeyInproc32);
+ }
+ RegCloseKey(hkeySub);
+ CoTaskMemFree(clsidString);
+ clsidString = NULL;
+ }
+
+ RegCloseKey(hkeyClsid);
+
+ return res;
}
diff -u -N -r -x *~ -x .#* -x CVS -x Makefile wine/dlls/devenum03/devenum_private.h wine/dlls/devenum/devenum_private.h
--- wine/dlls/devenum03/devenum_private.h Thu Jan 1 01:00:00 1970
+++ wine/dlls/devenum/devenum_private.h Mon Jun 30 00:34:31 2003
@@ -0,0 +1,115 @@
+/*
+ * includes 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
+ *
+ * NOTES ON FILE:
+ * - Private file where devenum globals are declared
+ */
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "winreg.h"
+#include "winerror.h"
+
+#define COM_NO_WINDOWS_H
+#include "ole2.h"
+#include "strmif.h"
+#include "wine/obj_property.h"
+#include "wine/unicode.h"
+#include "uuids.h"
+
+/**********************************************************************
+ * Dll lifetime tracking declaration for devenum.dll
+ */
+extern DWORD dll_ref;
+
+/**********************************************************************
+ * ClassFactory declaration for devenum.dll
+ */
+typedef struct
+{
+ /* IUnknown fields */
+ ICOM_VFIELD(IClassFactory);
+ DWORD ref;
+} ClassFactoryImpl;
+
+typedef struct
+{
+ ICOM_VFIELD(ICreateDevEnum);
+ DWORD ref;
+} CreateDevEnumImpl;
+
+typedef struct
+{
+ ICOM_VFIELD(IEnumMoniker);
+ DWORD ref;
+ DWORD index;
+ HKEY hkey;
+} EnumMonikerImpl;
+
+typedef struct
+{
+ ICOM_VFIELD(IMoniker);
+
+ DWORD ref;
+ HKEY hkey;
+} MediaCatMoniker;
+
+typedef struct
+{
+ ICOM_VFIELD(IPropertyBag);
+ DWORD ref;
+ HKEY hkey;
+} RegPropBagImpl;
+
+typedef struct
+{
+ ICOM_VFIELD(IParseDisplayName);
+ DWORD ref;
+} ParseDisplayNameImpl;
+
+MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct();
+HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
+ ICreateDevEnum * iface,
+ REFCLSID clsidDeviceClass,
+ IEnumMoniker **ppEnumMoniker,
+ DWORD dwFlags);
+
+extern ClassFactoryImpl DEVENUM_ClassFactory;
+extern CreateDevEnumImpl DEVENUM_CreateDevEnum;
+extern ParseDisplayNameImpl DEVENUM_ParseDisplayName;
+
+/**********************************************************************
+ * Global string constant declarations
+ */
+extern const WCHAR clsid_keyname[6];
+extern const WCHAR wszInstanceKeyName[];
+extern const WCHAR wszRegSeperator[];
+#define CLSID_STR_LEN (sizeof(clsid_keyname) / sizeof(WCHAR))
+
+/**********************************************************************
+ * Resource IDs
+ */
+#define IDS_DEVENUM_DSDEFAULT 7
+#define IDS_DEVENUM_DS 8
+#define IDS_DEVENUM_WODEFAULT 9
+#define IDS_DEVENUM_MIDEFAULT 10
+#define IDS_DEVENUM_KSDEFAULT 11
+#define IDS_DEVENUM_KS 12
diff -u -N -r -x *~ -x .#* -x CVS -x Makefile wine/dlls/devenum03/factory.c wine/dlls/devenum/factory.c
--- wine/dlls/devenum03/factory.c Thu Jan 1 01:00:00 1970
+++ wine/dlls/devenum/factory.c Fri Jun 27 00:19:32 2003
@@ -0,0 +1,155 @@
+/*
+ * ClassFactory implementation 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"
+
+WINE_DEFAULT_DEBUG_CHANNEL(devenum);
+
+/**********************************************************************
+ * DEVENUM_IClassFactory_QueryInterface (also IUnknown)
+ */
+static HRESULT WINAPI DEVENUM_IClassFactory_QueryInterface(
+ LPCLASSFACTORY iface,
+ REFIID riid,
+ LPVOID *ppvObj)
+{
+ ICOM_THIS(ClassFactoryImpl, 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_IClassFactory))
+ {
+ *ppvObj = (LPVOID)iface;
+ IClassFactory_AddRef(iface);
+ return S_OK;
+ }
+ else if (IsEqualGUID(riid, &IID_IParseDisplayName))
+ {
+ return IClassFactory_CreateInstance(iface, NULL, riid, ppvObj);
+ }
+
+ FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+}
+
+/**********************************************************************
+ * DEVENUM_IClassFactory_AddRef (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_IClassFactory_AddRef(LPCLASSFACTORY iface)
+{
+ ICOM_THIS(ClassFactoryImpl, iface);
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+
+ This->ref++;
+
+ if (InterlockedIncrement(&This->ref) == 1) {
+ InterlockedIncrement(&dll_ref);
+ }
+ return This->ref;
+}
+
+/**********************************************************************
+ * DEVENUM_IClassFactory_Release (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_IClassFactory_Release(LPCLASSFACTORY iface)
+{
+ ICOM_THIS(ClassFactoryImpl, iface);
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+
+ if (InterlockedDecrement(&This->ref) == 0) {
+ InterlockedDecrement(&dll_ref);
+ }
+ return This->ref;
+}
+
+/**********************************************************************
+ * DEVENUM_IClassFactory_CreateInstance
+ */
+static HRESULT WINAPI DEVENUM_IClassFactory_CreateInstance(
+ LPCLASSFACTORY iface,
+ LPUNKNOWN pUnkOuter,
+ REFIID riid,
+ LPVOID *ppvObj)
+{
+ ICOM_THIS(ClassFactoryImpl, iface);
+ TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+
+ if (This == NULL || ppvObj == NULL) return E_POINTER;
+
+ /* Don't support aggregation (Windows doesn't) */
+ if (pUnkOuter != NULL) return CLASS_E_NOAGGREGATION;
+
+ if (IsEqualGUID(&IID_ICreateDevEnum, riid))
+ {
+ *ppvObj = &DEVENUM_CreateDevEnum;
+ return S_OK;
+ }
+ if (IsEqualGUID(&IID_IParseDisplayName, riid))
+ {
+ *ppvObj = &DEVENUM_ParseDisplayName;
+ return S_OK;
+ }
+
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+/**********************************************************************
+ * DEVENUM_IClassFactory_LockServer
+ */
+static HRESULT WINAPI DEVENUM_IClassFactory_LockServer(
+ LPCLASSFACTORY iface,
+ BOOL fLock)
+{
+ TRACE("\n");
+
+ if (fLock != FALSE) {
+ IClassFactory_AddRef(iface);
+ } else {
+ IClassFactory_Release(iface);
+ }
+ return S_OK;
+}
+
+/**********************************************************************
+ * IClassFactory_Vtbl
+ */
+static ICOM_VTABLE(IClassFactory) IClassFactory_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ DEVENUM_IClassFactory_QueryInterface,
+ DEVENUM_IClassFactory_AddRef,
+ DEVENUM_IClassFactory_Release,
+ DEVENUM_IClassFactory_CreateInstance,
+ DEVENUM_IClassFactory_LockServer
+};
+
+/**********************************************************************
+ * static ClassFactory instance
+ */
+ClassFactoryImpl DEVENUM_ClassFactory = { &IClassFactory_Vtbl, 0 };
diff -u -N -r -x *~ -x .#* -x CVS -x Makefile wine/dlls/devenum03/mediacatenum.c wine/dlls/devenum/mediacatenum.c
--- wine/dlls/devenum03/mediacatenum.c Thu Jan 1 01:00:00 1970
+++ wine/dlls/devenum/mediacatenum.c Sun Jun 29 23:52:28 2003
@@ -0,0 +1,800 @@
+/*
+ * 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 HRESULT WINAPI DEVENUM_IMediaCatMoniker_Hash(LPMONIKER iface, DWORD* pdwHash);
+static ULONG WINAPI DEVENUM_IMediaCatMoniker_AddRef(LPMONIKER iface);
+static ULONG WINAPI DEVENUM_IPropertyBag_AddRef(LPPROPERTYBAG iface);
+
+static HRESULT WINAPI DEVENUM_IPropertyBag_QueryInterface(
+ LPPROPERTYBAG iface,
+ REFIID riid,
+ LPVOID *ppvObj)
+{
+ ICOM_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)
+{
+ ICOM_THIS(RegPropBagImpl, iface);
+ TRACE("\n");
+
+ return InterlockedIncrement(&This->ref);
+}
+
+/**********************************************************************
+ * DEVENUM_IPropertyBag_Release (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_IPropertyBag_Release(LPPROPERTYBAG iface)
+{
+ ICOM_THIS(RegPropBagImpl, iface);
+
+ TRACE("\n");
+
+ if (InterlockedDecrement(&This->ref) == 0) {
+ RegCloseKey(This->hkey);
+ CoTaskMemFree(This);
+ return 0;
+ }
+ return This->ref;
+}
+
+static const WCHAR wszNull = '\0';
+
+static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
+ LPPROPERTYBAG iface,
+ LPCOLESTR pszPropName,
+ VARIANT* pVar,
+ IErrorLog* pErrorLog)
+{
+ WCHAR wszData[MAX_PATH + 1];
+ LONG received = MAX_PATH + 1;
+ DWORD type = 0;
+ ICOM_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;
+
+ /* work around a GCC bug that occurs here unless we use the reswin32 variable as well */
+ reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, &type, (LPVOID)wszData, &received);
+ res = HRESULT_FROM_WIN32(reswin32);
+
+ if (SUCCEEDED(res))
+ {
+ TRACE("%ld, %s\n", received, debugstr_w(wszData));
+ switch (type)
+ {
+ case REG_SZ:
+ switch (V_VT(pVar))
+ {
+ case VT_LPWSTR:
+ V_UNION(pVar, bstrVal) = CoTaskMemAlloc(received * sizeof(WCHAR));
+ strcpyW(V_UNION(pVar, bstrVal), wszData);
+ return S_OK;
+ case VT_EMPTY:
+ V_VT(pVar) = VT_BSTR;
+ /* fall through */
+ case VT_BSTR:
+ V_UNION(pVar, bstrVal) = SysAllocStringLen(wszData, received - 1);
+ return S_OK;
+ }
+ break;
+ case REG_DWORD:
+ TRACE("REG_DWORD: %lx\n", *(DWORD *)wszData);
+ 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 *)wszData;
+ return S_OK;
+ }
+ 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)))
+ return E_OUTOFMEMORY;
+ break;
+ }
+
+ res = SafeArrayAccessData(V_UNION(pVar, parray), &pArrayElements);
+ if (FAILED(res))
+ {
+ TRACE(" <- %lx\n", res);
+ return res;
+ }
+ CopyMemory(pArrayElements, wszData, received);
+ res = SafeArrayUnaccessData(V_UNION(pVar, parray));
+ TRACE(" <- %lx\n", res);
+ return res;
+ }
+ }
+ FIXME("Variant type %x not supported for regtype %lx\n", V_VT(pVar), type);
+ return E_FAIL;
+ }
+
+ TRACE("<- %lx\n", res);
+ return res;
+}
+
+static HRESULT WINAPI DEVENUM_IPropertyBag_Write(
+ LPPROPERTYBAG iface,
+ LPCOLESTR pszPropName,
+ VARIANT* pVar)
+{
+ ICOM_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:
+ 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 ICOM_VTABLE(IPropertyBag) IPropertyBag_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ DEVENUM_IPropertyBag_QueryInterface,
+ DEVENUM_IPropertyBag_AddRef,
+ DEVENUM_IPropertyBag_Release,
+ DEVENUM_IPropertyBag_Read,
+ DEVENUM_IPropertyBag_Write
+};
+
+
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_QueryInterface(
+ LPMONIKER iface,
+ REFIID riid,
+ LPVOID *ppvObj)
+{
+ ICOM_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)
+{
+ ICOM_THIS(MediaCatMoniker, iface);
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+
+ return ++This->ref;
+}
+
+/**********************************************************************
+ * DEVENUM_IMediaCatMoniker_Release (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_IMediaCatMoniker_Release(LPMONIKER iface)
+{
+ ICOM_THIS(MediaCatMoniker, iface);
+ ULONG ref;
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+
+ ref = --This->ref;
+ if (ref == 0) {
+ RegCloseKey(This->hkey);
+ CoTaskMemFree(This);
+ }
+ return ref;
+}
+
+static HRESULT WINAPI DEVENUM_IMediaCatMoniker_GetClassID(
+ LPMONIKER iface,
+ CLSID* pClassID)
+{
+ ICOM_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;
+
+ ICOM_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 */
+ res=IMoniker_BindToStorage(iface, NULL, NULL, &IID_IPropertyBag, (void**)&pProp);
+ 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,(void**)&pObj);
+ }
+ }
+
+ 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)
+{
+ ICOM_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))
+ {
+ RegPropBagImpl * rpb = CoTaskMemAlloc(sizeof(RegPropBagImpl));
+ if (!rpb)
+ return E_OUTOFMEMORY;
+ rpb->lpVtbl = &IPropertyBag_Vtbl;
+ DuplicateHandle(GetCurrentProcess(), This->hkey, GetCurrentProcess(), (LPHANDLE)&(rpb->hkey), 0, 0, DUPLICATE_SAME_ACCESS);
+ rpb->ref = 1;
+ *ppvObj = (LPVOID)rpb;
+ return S_OK;
+ }
+
+ 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)
+{
+ ICOM_THIS(MediaCatMoniker, iface);
+ WCHAR wszBuffer[MAX_PATH];
+ 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 ICOM_VTABLE(IMoniker) IMoniker_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ 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);
+
+ return pMoniker;
+}
+
+/**********************************************************************
+ * DEVENUM_IEnumMoniker_QueryInterface (also IUnknown)
+ */
+static HRESULT WINAPI DEVENUM_IEnumMoniker_QueryInterface(
+ LPENUMMONIKER iface,
+ REFIID riid,
+ LPVOID *ppvObj)
+{
+ ICOM_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)
+{
+ ICOM_THIS(EnumMonikerImpl, iface);
+
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+
+ return InterlockedIncrement(&This->ref);
+}
+
+/**********************************************************************
+ * DEVENUM_IEnumMoniker_Release (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_IEnumMoniker_Release(LPENUMMONIKER iface)
+{
+ ICOM_THIS(EnumMonikerImpl, iface);
+
+ TRACE("\n");
+
+ if (!InterlockedDecrement(&This->ref))
+ {
+ RegCloseKey(This->hkey);
+ CoTaskMemFree(This);
+ 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;
+ ICOM_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)
+{
+ ICOM_THIS(EnumMonikerImpl, iface);
+
+ TRACE("(%ld)\n", celt);
+
+ This->index += celt;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI DEVENUM_IEnumMoniker_Reset(LPENUMMONIKER iface)
+{
+ ICOM_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
+ */
+ICOM_VTABLE(IEnumMoniker) IEnumMoniker_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ DEVENUM_IEnumMoniker_QueryInterface,
+ DEVENUM_IEnumMoniker_AddRef,
+ DEVENUM_IEnumMoniker_Release,
+ DEVENUM_IEnumMoniker_Next,
+ DEVENUM_IEnumMoniker_Skip,
+ DEVENUM_IEnumMoniker_Reset,
+ DEVENUM_IEnumMoniker_Clone
+};
diff -u -N -r -x *~ -x .#* -x CVS -x Makefile wine/dlls/devenum03/parsedisplayname.c wine/dlls/devenum/parsedisplayname.c
--- wine/dlls/devenum03/parsedisplayname.c Thu Jan 1 01:00:00 1970
+++ wine/dlls/devenum/parsedisplayname.c Mon Jun 30 00:33:45 2003
@@ -0,0 +1,177 @@
+/*
+ * IParseDisplayName 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 IParseDisplayName interface which creates a moniker
+ * from a string in a special format
+ */
+#include "devenum_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(devenum);
+
+static HRESULT WINAPI DEVENUM_IParseDisplayName_QueryInterface(
+ LPPARSEDISPLAYNAME iface,
+ REFIID riid,
+ LPVOID *ppvObj)
+{
+ ICOM_THIS(ParseDisplayNameImpl, 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_IParseDisplayName))
+ {
+ *ppvObj = (LPVOID)iface;
+ IParseDisplayName_AddRef(iface);
+ return S_OK;
+ }
+
+ FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+}
+
+/**********************************************************************
+ * DEVENUM_IParseDisplayName_AddRef (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_IParseDisplayName_AddRef(LPPARSEDISPLAYNAME iface)
+{
+ ICOM_THIS(ParseDisplayNameImpl, iface);
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+
+ if (InterlockedIncrement(&This->ref) == 1) {
+ InterlockedIncrement(&dll_ref);
+ }
+
+ return ++This->ref;
+}
+
+/**********************************************************************
+ * DEVENUM_IParseDisplayName_Release (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_IParseDisplayName_Release(LPPARSEDISPLAYNAME iface)
+{
+ ICOM_THIS(ParseDisplayNameImpl, iface);
+ ULONG ref;
+ TRACE("\n");
+
+ if (This == NULL) return E_POINTER;
+
+ ref = --This->ref;
+ if (InterlockedDecrement(&This->ref) == 0) {
+ InterlockedDecrement(&dll_ref);
+ }
+ return ref;
+}
+
+/**********************************************************************
+ * DEVENUM_IParseDisplayName_ParseDisplayName
+ *
+ * Creates a moniker referenced to by the display string argument
+ *
+ * POSSIBLE BUGS:
+ * Might not handle more complicated strings properly (ie not in
+ * "@device:sw:{CLSID1}\{CLSID2}" format
+ */
+static HRESULT WINAPI DEVENUM_IParseDisplayName_ParseDisplayName(
+ LPPARSEDISPLAYNAME iface,
+ IBindCtx *pbc,
+ LPOLESTR pszDisplayName,
+ ULONG *pchEaten,
+ IMoniker **ppmkOut)
+{
+ LPOLESTR pszBetween = NULL;
+ LPOLESTR pszClass = NULL;
+ IEnumMoniker * pEm = NULL;
+ MediaCatMoniker * pMoniker = NULL;
+ CLSID clsidDevice;
+ HRESULT res = S_OK;
+ TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(pszDisplayName), pchEaten, ppmkOut);
+
+ *ppmkOut = NULL;
+ if (pchEaten)
+ *pchEaten = strlenW(pszDisplayName);
+
+ pszDisplayName = strchrW(pszDisplayName, '{');
+ pszBetween = strchrW(pszDisplayName, '}') + 2;
+
+ /* size = pszBetween - pszDisplayName - 1 (for '\\' after CLSID)
+ * + 1 (for NULL character)
+ */
+ pszClass = CoTaskMemAlloc((int)(pszBetween - pszDisplayName) * sizeof(WCHAR));
+ if (!pszClass)
+ return E_OUTOFMEMORY;
+
+ strncpyW(pszClass, pszDisplayName, (int)(pszBetween - pszDisplayName) - 1);
+ pszClass[(int)(pszBetween - pszDisplayName) - 1] = 0;
+
+ TRACE("Device CLSID: %s\n", debugstr_w(pszClass));
+
+ res = CLSIDFromString(pszClass, &clsidDevice);
+
+ if (SUCCEEDED(res))
+ {
+ res = DEVENUM_ICreateDevEnum_CreateClassEnumerator((ICreateDevEnum *)&DEVENUM_CreateDevEnum, &clsidDevice, &pEm, 0);
+ }
+
+ if (SUCCEEDED(res))
+ {
+ pMoniker = DEVENUM_IMediaCatMoniker_Construct();
+ if (pMoniker)
+ {
+ if (RegCreateKeyW(((EnumMonikerImpl *)pEm)->hkey,
+ pszBetween,
+ &pMoniker->hkey) == ERROR_SUCCESS)
+ *ppmkOut = (LPMONIKER)pMoniker;
+ else
+ {
+ IMoniker_Release((LPMONIKER)pMoniker);
+ res = MK_E_NOOBJECT;
+ }
+ }
+ }
+
+ if (pEm)
+ IEnumMoniker_Release(pEm);
+
+ if (pszClass)
+ CoTaskMemFree(pszClass);
+
+ TRACE("-- returning: %lx\n", res);
+ return res;
+}
+
+/**********************************************************************
+ * IParseDisplayName_Vtbl
+ */
+static ICOM_VTABLE(IParseDisplayName) IParseDisplayName_Vtbl =
+{
+ ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+ DEVENUM_IParseDisplayName_QueryInterface,
+ DEVENUM_IParseDisplayName_AddRef,
+ DEVENUM_IParseDisplayName_Release,
+ DEVENUM_IParseDisplayName_ParseDisplayName
+};
+
+/* The one instance of this class */
+ParseDisplayNameImpl DEVENUM_ParseDisplayName = { &IParseDisplayName_Vtbl, 0 };