Commit in reactos/lib/devenum on MAIN
Makefile.in+20added 1.1
Makefile.ros-template+29added 1.1
createdevenum.c+437added 1.1
devenum.rc+79added 1.1
devenum.spec+4added 1.1
devenum_main.c+389added 1.1
devenum_private.h+110added 1.1
factory.c+141added 1.1
makefile+9added 1.1
mediacatenum.c+848added 1.1
parsedisplayname.c+167added 1.1
+2233
11 added files
port over devnum from wine only small change to createdevnum.c

reactos/lib/devenum
Makefile.in added at 1.1
diff -N Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Makefile.in	20 Dec 2004 22:09:31 -0000	1.1
@@ -0,0 +1,20 @@
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = devenum.dll
+IMPORTS   = ole32 oleaut32 winmm user32 advapi32 kernel32
+EXTRALIBS = -lstrmiids -luuid
+
+C_SRCS = \
+	createdevenum.c \
+	devenum_main.c \
+	factory.c \
+	mediacatenum.c \
+	parsedisplayname.c
+
+RC_SRCS = devenum.rc
+
+@MAKE_DLL_RULES@
+
+### Dependencies:

reactos/lib/devenum
Makefile.ros-template added at 1.1
diff -N Makefile.ros-template
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Makefile.ros-template	20 Dec 2004 22:09:31 -0000	1.1
@@ -0,0 +1,29 @@
+# $Id: Makefile.ros-template,v 1.1 2004/12/20 22:09:31 greatlrd Exp $
+
+TARGET_NAME = devenum
+
+TARGET_OBJECTS = @C_SRCS@
+
+TARGET_CFLAGS = @EXTRADEFS@ -DNONAMLESSUNION -D__REACTOS__
+
+TARGET_SDKLIBS = wine.a @IMPORTS@ ole32.a wine_uuid.a ntdll.a  dxguid.a strmiids.a
+
+
+TARGET_BASE = $(TARGET_BASE_LIB_DEVNUM)
+
+TARGET_RC_SRCS = @RC_SRCS@
+TARGET_RC_BINSRC = @RC_BINSRC@
+TARGET_RC_BINARIES = @RC_BINARIES@
+
+default: all
+
+authors.c:
+ifeq ($(HOST),mingw32-linux)
+	echo 'const char * const SHELL_Authors[] = { "WINE team", "ReactOS team", 0 };' > authors.c
+else
+	echo const char * const SHELL_Authors[] = { "WINE team", "ReactOS team", 0 }; > authors.c
+endif
+
+DEP_OBJECTS = $(TARGET_OBJECTS)
+
+include $(TOOLS_PATH)/depend.mk

reactos/lib/devenum
createdevenum.c added at 1.1
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
devenum.rc added at 1.1
diff -N devenum.rc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ devenum.rc	20 Dec 2004 22:09:31 -0000	1.1
@@ -0,0 +1,79 @@
+/*
+ * 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 "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+#define WINE_FILEDESCRIPTION_STR "Wine Device Enumerator Library"
+#define WINE_FILENAME_STR "devenum.dll"
+#define WINE_FILEVERSION 6,5,1,902
+#define WINE_FILEVERSION_STR "6.5.1.902"
+#define WINE_PRODUCTVERSION 6,5,1,902
+#define WINE_PRODUCTVERSION_STR "6.5"
+
+#include "wine/wine_common_ver.rc"
+
+STRINGTABLE DISCARDABLE
+LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
+{
+	7  "Default DirectSound"
+	8  "DirectSound: %s"
+	9  "Default WaveOut Device"
+	10 "Default MidiOut Device"
+}
+
+STRINGTABLE DISCARDABLE
+LANGUAGE LANG_GERMAN, SUBLANG_DEFAULT
+{
+	7  "Standard DirectSound"
+	8  "DirectSound: %s"
+	9  "Standard WaveOut - Ger�t"
+	10 "Standard MidiOut - Ger�t"
+}
+
+STRINGTABLE DISCARDABLE
+LANGUAGE LANG_ITALIAN, SUBLANG_DEFAULT
+{
+	7  "DirectSound di Default"
+	8  "DirectSound: %s"
+	9  "Dispositivo WaveOut di Default"
+	10 "Dispositivo MidiOut di Default"
+}
+
+STRINGTABLE DISCARDABLE
+LANGUAGE LANG_PORTUGUESE, SUBLANG_DEFAULT
+{
+	7  "DirectSound padr�o"
+	8  "DirectSound: %s"
+	9  "Dispositivo padr�o WaveOut"
+	10 "Dispositivo padr�o MidiOut"
+}
+
+STRINGTABLE DISCARDABLE
+LANGUAGE LANG_SPANISH, SUBLANG_DEFAULT
+{
+	7  "DirectSound por defecto"
+	8  "DirectSound: %s"
+	9  "Dispositivo WaveOut por defecto"
+	10 "Dispositivo MidiOut por defecto"
+}

reactos/lib/devenum
devenum.spec added at 1.1
diff -N devenum.spec
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ devenum.spec	20 Dec 2004 22:09:31 -0000	1.1
@@ -0,0 +1,4 @@
+@ stdcall -private DllCanUnloadNow() DEVENUM_DllCanUnloadNow
+@ stdcall -private DllGetClassObject(ptr ptr ptr) DEVENUM_DllGetClassObject
+@ stdcall -private DllRegisterServer() DEVENUM_DllRegisterServer
+@ stdcall -private DllUnregisterServer() DEVENUM_DllUnregisterServer

reactos/lib/devenum
devenum_main.c added at 1.1
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
devenum_private.h added at 1.1
diff -N devenum_private.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ devenum_private.h	20 Dec 2004 22:09:31 -0000	1.1
@@ -0,0 +1,110 @@
+/*
+ *	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 <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "winreg.h"
+#include "winerror.h"
+
+#define COBJMACROS
+#define COM_NO_WINDOWS_H
+
+#include "ole2.h"
+#include "olectl.h"
+#include "wine/unicode.h"
+#include "uuids.h"
+#include "strmif.h"
+/**********************************************************************
+ * Dll lifetime tracking declaration for devenum.dll
+ */
+extern LONG dll_refs;
+static inline void DEVENUM_LockModule(void) { InterlockedIncrement(&dll_refs); }
+static inline void DEVENUM_UnlockModule(void) { InterlockedDecrement(&dll_refs); }
+
+
+/**********************************************************************
+ * ClassFactory declaration for devenum.dll
+ */
+typedef struct
+{
+    IClassFactoryVtbl *lpVtbl;
+} ClassFactoryImpl;
+
+typedef struct
+{
+    ICreateDevEnumVtbl *lpVtbl;
+} CreateDevEnumImpl;
+
+typedef struct
+{
+    IParseDisplayNameVtbl *lpVtbl;
+} ParseDisplayNameImpl;
+
+typedef struct
+{
+    IEnumMonikerVtbl *lpVtbl;
+    DWORD ref;
+    DWORD index;
+    HKEY hkey;
+} EnumMonikerImpl;
+
+typedef struct
+{
+    IMonikerVtbl *lpVtbl;
+
+    ULONG ref;
+    HKEY hkey;
+} MediaCatMoniker;
+
+MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void);
+HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker);
+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[];
+#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

reactos/lib/devenum
factory.c added at 1.1
diff -N factory.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ factory.c	20 Dec 2004 22:09:31 -0000	1.1
@@ -0,0 +1,141 @@
+/*
+ *	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)
+{
+    TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+
+    if (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)
+{
+    TRACE("\n");
+
+    DEVENUM_LockModule();
+
+    return 2; /* non-heap based object */
+}
+
+/**********************************************************************
+ * DEVENUM_IClassFactory_Release (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_IClassFactory_Release(LPCLASSFACTORY iface)
+{
+    TRACE("\n");
+
+    DEVENUM_UnlockModule();
+
+    return 1; /* non-heap based object */
+}
+
+/**********************************************************************
+ * DEVENUM_IClassFactory_CreateInstance
+ */
+static HRESULT WINAPI DEVENUM_IClassFactory_CreateInstance(
+    LPCLASSFACTORY iface,
+    LPUNKNOWN pUnkOuter,
+    REFIID riid,
+    LPVOID *ppvObj)
+{
+    TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+
+    if (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)
+        DEVENUM_LockModule();
+    else
+        DEVENUM_UnlockModule();
+    return S_OK;
+}
+
+/**********************************************************************
+ * IClassFactory_Vtbl
+ */
+static IClassFactoryVtbl IClassFactory_Vtbl =
+{
+    DEVENUM_IClassFactory_QueryInterface,
+    DEVENUM_IClassFactory_AddRef,
+    DEVENUM_IClassFactory_Release,
+    DEVENUM_IClassFactory_CreateInstance,
+    DEVENUM_IClassFactory_LockServer
+};
+
+/**********************************************************************
+ * static ClassFactory instance
+ */
+ClassFactoryImpl DEVENUM_ClassFactory = { &IClassFactory_Vtbl };

reactos/lib/devenum
makefile added at 1.1
diff -N makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ makefile	20 Dec 2004 22:09:31 -0000	1.1
@@ -0,0 +1,9 @@
+# $Id: makefile,v 1.1 2004/12/20 22:09:31 greatlrd Exp $
+
+PATH_TO_TOP = ../..
+
+TARGET_TYPE = winedll
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk

reactos/lib/devenum
mediacatenum.c added at 1.1
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;
+}

reactos/lib/devenum
parsedisplayname.c added at 1.1
diff -N parsedisplayname.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ parsedisplayname.c	20 Dec 2004 22:09:31 -0000	1.1
@@ -0,0 +1,167 @@
+/*
+ *	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)
+{
+    TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+
+    if (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)
+{
+    TRACE("\n");
+
+    DEVENUM_LockModule();
+
+    return 2; /* non-heap based object */
+}
+
+/**********************************************************************
+ * DEVENUM_IParseDisplayName_Release (also IUnknown)
+ */
+static ULONG WINAPI DEVENUM_IParseDisplayName_Release(LPPARSEDISPLAYNAME iface)
+{
+    TRACE("\n");
+
+    DEVENUM_UnlockModule();
+
+    return 1; /* non-heap based object */
+}
+
+/**********************************************************************
+ * DEVENUM_IParseDisplayName_ParseDisplayName
+ *
+ *  Creates a moniker referenced to by the display string argument
+ *
+ * POSSIBLE BUGS:
+ *  Might not handle more complicated strings properly (ie anything
+ *  not in "@device:sw:{CLSID1}\<filter name or CLSID>" 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 *)(char*)&DEVENUM_CreateDevEnum, &clsidDevice, &pEm, 0);
+        if (res == S_FALSE) /* S_FALSE means no category */
+            res = MK_E_NOOBJECT;
+    }
+
+    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 IParseDisplayNameVtbl IParseDisplayName_Vtbl =
+{
+    DEVENUM_IParseDisplayName_QueryInterface,
+    DEVENUM_IParseDisplayName_AddRef,
+    DEVENUM_IParseDisplayName_Release,
+    DEVENUM_IParseDisplayName_ParseDisplayName
+};
+
+/* The one instance of this class */
+ParseDisplayNameImpl DEVENUM_ParseDisplayName = { &IParseDisplayName_Vtbl };
CVSspam 0.2.8