Implemented DevEnum dll.
diff --git a/dlls/devenum/parsedisplayname.c b/dlls/devenum/parsedisplayname.c new file mode 100644 index 0000000..b5b1c13 --- /dev/null +++ b/dlls/devenum/parsedisplayname.c
@@ -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 };