Implemented DevEnum dll.
This commit is contained in:
parent
c71301a308
commit
d38cce8d4b
|
@ -1,4 +1,5 @@
|
|||
Makefile
|
||||
devenum.dll.dbg.c
|
||||
devenum.res
|
||||
devenum.spec.c
|
||||
devenum.spec.def
|
||||
|
|
|
@ -3,11 +3,20 @@ TOPOBJDIR = ../..
|
|||
SRCDIR = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
MODULE = devenum.dll
|
||||
IMPORTS = ole32 oleaut32 winmm user32 advapi32 kernel32
|
||||
EXTRALIBS = $(LIBUUID)
|
||||
|
||||
LDDLLFLAGS = @LDDLLFLAGS@
|
||||
SYMBOLFILE = $(MODULE).tmp.o
|
||||
|
||||
C_SRCS = devenum_main.c
|
||||
C_SRCS = \
|
||||
createdevenum.c \
|
||||
devenum_main.c \
|
||||
factory.c \
|
||||
mediacatenum.c \
|
||||
parsedisplayname.c
|
||||
|
||||
RC_SRCS = devenum.rc
|
||||
|
||||
@MAKE_DLL_RULES@
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
/***********************************************************************
|
||||
* DllRegisterServer (DEVENUM.@)
|
||||
*/
|
||||
HRESULT WINAPI DEVENUM_DllRegisterServer()
|
||||
DWORD dll_ref = 0;
|
||||
HINSTANCE DEVENUM_hInstance;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FIXME("(): stub\n");
|
||||
return 0;
|
||||
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;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DllCanUnloadNow (DEVENUM.@)
|
||||
*/
|
||||
HRESULT WINAPI DEVENUM_DllCanUnloadNow(void)
|
||||
{
|
||||
return dll_ref != 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;
|
||||
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(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;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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 };
|
|
@ -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
|
||||
};
|
|
@ -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 };
|
Loading…
Reference in New Issue