[01/12] fusion: Implement the IAssemblyEnum interface.
Hans Leidekker
hans at codeweavers.com
Wed Feb 18 07:34:54 CST 2009
Changelog
"James Hawkins" <truiken at gmail.com>
fusion: Implement the IAssemblyEnum interface.
-Hans
diff --git a/dlls/fusion/Makefile.in b/dlls/fusion/Makefile.in
index 851fafc..788e188 100644
--- a/dlls/fusion/Makefile.in
+++ b/dlls/fusion/Makefile.in
@@ -7,6 +7,7 @@ IMPORTS = advapi32 dbghelp kernel32 shlwapi version
C_SRCS = \
asmcache.c \
+ asmenum.c \
asmname.c \
assembly.c \
fusion.c \
diff --git a/dlls/fusion/asmcache.c b/dlls/fusion/asmcache.c
index 57c7aed..d205de1 100644
--- a/dlls/fusion/asmcache.c
+++ b/dlls/fusion/asmcache.c
@@ -391,86 +391,3 @@ static const IAssemblyCacheItemVtbl AssemblyCacheItemVtbl = {
IAssemblyCacheItemImpl_Commit,
IAssemblyCacheItemImpl_AbortItem
};
-
-/* IAssemblyEnum */
-
-typedef struct {
- const IAssemblyEnumVtbl *lpIAssemblyEnumVtbl;
-
- LONG ref;
-} IAssemblyEnumImpl;
-
-static HRESULT WINAPI IAssemblyEnumImpl_QueryInterface(IAssemblyEnum *iface,
- REFIID riid, LPVOID *ppobj)
-{
- IAssemblyEnumImpl *This = (IAssemblyEnumImpl *)iface;
-
- TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
-
- *ppobj = NULL;
-
- if (IsEqualIID(riid, &IID_IUnknown) ||
- IsEqualIID(riid, &IID_IAssemblyEnum))
- {
- IUnknown_AddRef(iface);
- *ppobj = This;
- return S_OK;
- }
-
- WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ppobj);
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI IAssemblyEnumImpl_AddRef(IAssemblyEnum *iface)
-{
- IAssemblyEnumImpl *This = (IAssemblyEnumImpl *)iface;
- ULONG refCount = InterlockedIncrement(&This->ref);
-
- TRACE("(%p)->(ref before = %u)\n", This, refCount - 1);
-
- return refCount;
-}
-
-static ULONG WINAPI IAssemblyEnumImpl_Release(IAssemblyEnum *iface)
-{
- IAssemblyEnumImpl *This = (IAssemblyEnumImpl *)iface;
- ULONG refCount = InterlockedDecrement(&This->ref);
-
- TRACE("(%p)->(ref before = %u)\n", This, refCount + 1);
-
- if (!refCount)
- HeapFree(GetProcessHeap(), 0, This);
-
- return refCount;
-}
-
-static HRESULT WINAPI IAssemblyEnumImpl_GetNextAssembly(IAssemblyEnum *iface,
- LPVOID pvReserved,
- IAssemblyName **ppName,
- DWORD dwFlags)
-{
- FIXME("(%p, %p, %p, %d) stub!\n", iface, pvReserved, ppName, dwFlags);
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI IAssemblyEnumImpl_Reset(IAssemblyEnum *iface)
-{
- FIXME("(%p) stub!\n", iface);
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI IAssemblyEnumImpl_Clone(IAssemblyEnum *iface,
- IAssemblyEnum **ppEnum)
-{
- FIXME("(%p, %p) stub!\n", iface, ppEnum);
- return E_NOTIMPL;
-}
-
-static const IAssemblyEnumVtbl AssemblyEnumVtbl = {
- IAssemblyEnumImpl_QueryInterface,
- IAssemblyEnumImpl_AddRef,
- IAssemblyEnumImpl_Release,
- IAssemblyEnumImpl_GetNextAssembly,
- IAssemblyEnumImpl_Reset,
- IAssemblyEnumImpl_Clone
-};
diff --git a/dlls/fusion/asmenum.c b/dlls/fusion/asmenum.c
new file mode 100644
index 0000000..929fff2
--- /dev/null
+++ b/dlls/fusion/asmenum.c
@@ -0,0 +1,384 @@
+/*
+ * IAssemblyEnum implementation
+ *
+ * Copyright 2008 James Hawkins
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "ole2.h"
+#include "guiddef.h"
+#include "fusion.h"
+#include "corerror.h"
+#include "fusionpriv.h"
+
+#include "wine/debug.h"
+#include "wine/unicode.h"
+#include "wine/list.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(fusion);
+
+typedef struct _tagASMNAME
+{
+ struct list entry;
+ IAssemblyName *name;
+} ASMNAME;
+
+typedef struct
+{
+ const IAssemblyEnumVtbl *lpIAssemblyEnumVtbl;
+
+ struct list assemblies;
+ struct list *iter;
+ LONG ref;
+} IAssemblyEnumImpl;
+
+static HRESULT WINAPI IAssemblyEnumImpl_QueryInterface(IAssemblyEnum *iface,
+ REFIID riid, LPVOID *ppobj)
+{
+ IAssemblyEnumImpl *This = (IAssemblyEnumImpl *)iface;
+
+ TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
+
+ *ppobj = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown) ||
+ IsEqualIID(riid, &IID_IAssemblyEnum))
+ {
+ IUnknown_AddRef(iface);
+ *ppobj = This;
+ return S_OK;
+ }
+
+ WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ppobj);
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI IAssemblyEnumImpl_AddRef(IAssemblyEnum *iface)
+{
+ IAssemblyEnumImpl *This = (IAssemblyEnumImpl *)iface;
+ ULONG refCount = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p)->(ref before = %u)\n", This, refCount - 1);
+
+ return refCount;
+}
+
+static ULONG WINAPI IAssemblyEnumImpl_Release(IAssemblyEnum *iface)
+{
+ IAssemblyEnumImpl *This = (IAssemblyEnumImpl *)iface;
+ ULONG refCount = InterlockedDecrement(&This->ref);
+ struct list *item, *cursor;
+
+ TRACE("(%p)->(ref before = %u)\n", This, refCount + 1);
+
+ if (!refCount)
+ {
+ LIST_FOR_EACH_SAFE(item, cursor, &This->assemblies)
+ {
+ ASMNAME *asmname = LIST_ENTRY(item, ASMNAME, entry);
+
+ list_remove(&asmname->entry);
+ IAssemblyName_Release(asmname->name);
+ HeapFree(GetProcessHeap(), 0, asmname);
+ }
+
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return refCount;
+}
+
+static HRESULT WINAPI IAssemblyEnumImpl_GetNextAssembly(IAssemblyEnum *iface,
+ LPVOID pvReserved,
+ IAssemblyName **ppName,
+ DWORD dwFlags)
+{
+ IAssemblyEnumImpl *asmenum = (IAssemblyEnumImpl *)iface;
+ ASMNAME *asmname;
+
+ TRACE("(%p, %p, %p, %d)\n", iface, pvReserved, ppName, dwFlags);
+
+ if (!ppName)
+ return E_INVALIDARG;
+
+ asmname = LIST_ENTRY(asmenum->iter, ASMNAME, entry);
+ if (!asmname)
+ return S_FALSE;
+
+ *ppName = asmname->name;
+ IAssemblyName_AddRef(*ppName);
+
+ asmenum->iter = list_next(&asmenum->assemblies, asmenum->iter);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI IAssemblyEnumImpl_Reset(IAssemblyEnum *iface)
+{
+ IAssemblyEnumImpl *asmenum = (IAssemblyEnumImpl *)iface;
+
+ TRACE("(%p)\n", iface);
+
+ asmenum->iter = list_head(&asmenum->assemblies);
+ return S_OK;
+}
+
+static HRESULT WINAPI IAssemblyEnumImpl_Clone(IAssemblyEnum *iface,
+ IAssemblyEnum **ppEnum)
+{
+ FIXME("(%p, %p) stub!\n", iface, ppEnum);
+ return E_NOTIMPL;
+}
+
+static const IAssemblyEnumVtbl AssemblyEnumVtbl = {
+ IAssemblyEnumImpl_QueryInterface,
+ IAssemblyEnumImpl_AddRef,
+ IAssemblyEnumImpl_Release,
+ IAssemblyEnumImpl_GetNextAssembly,
+ IAssemblyEnumImpl_Reset,
+ IAssemblyEnumImpl_Clone
+};
+
+static void parse_name(IAssemblyName *name, int depth, LPWSTR path, LPWSTR buf)
+{
+ WCHAR disp[MAX_PATH];
+ LPWSTR ptr, end;
+ LPCWSTR verptr, pubkeyptr;
+ HRESULT hr;
+ DWORD size;
+
+ static const WCHAR star[] = {'*',0};
+ static const WCHAR ss_fmt[] = {'%','s','\\','%','s',0};
+ static const WCHAR verpubkey[] = {'%','s','\\','%','s','_','_','%','s',0};
+ static const WCHAR version[] = {'V','e','r','s','i','o','n','=',0};
+ static const WCHAR pubkeytok[] = {
+ 'P','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
+
+ if (depth == 0)
+ {
+ size = MAX_PATH;
+ *disp = '\0';
+ hr = IAssemblyName_GetName(name, &size, disp);
+ if (SUCCEEDED(hr))
+ sprintfW(buf, ss_fmt, path, disp);
+ else
+ sprintfW(buf, ss_fmt, path, star);
+ }
+ else if (depth == 1)
+ {
+ size = MAX_PATH;
+ hr = IAssemblyName_GetDisplayName(name, disp, &size, 0);
+ if (FAILED(hr))
+ {
+ sprintfW(buf, verpubkey, path, star, star);
+ return;
+ }
+
+ ptr = disp;
+ verptr = strstrW(ptr, version);
+ if (!verptr)
+ verptr = star;
+ else
+ {
+ verptr = strchrW(verptr, '=') + 1;
+ if ((end = strchrW(verptr, ',')))
+ {
+ *end = '\0';
+ ptr = end + 1;
+ }
+ }
+
+ pubkeyptr = strstrW(ptr, pubkeytok);
+ if (!pubkeyptr)
+ pubkeyptr = star;
+ else
+ {
+ pubkeyptr = strchrW(pubkeyptr, '=') + 1;
+ if ((end = strchrW(pubkeyptr, ',')))
+ *end = '\0';
+ }
+
+ sprintfW(buf, verpubkey, path, verptr, pubkeyptr);
+ }
+}
+
+static HRESULT enum_gac_assemblies(struct list *assemblies, IAssemblyName *name,
+ int depth, LPWSTR path)
+{
+ WIN32_FIND_DATAW ffd;
+ WCHAR buf[MAX_PATH];
+ WCHAR disp[MAX_PATH];
+ ASMNAME *asmname;
+ HANDLE hfind;
+ LPWSTR ptr;
+ HRESULT hr = S_OK;
+
+ static WCHAR parent[MAX_PATH];
+
+ static const WCHAR dot[] = {'.',0};
+ static const WCHAR dotdot[] = {'.','.',0};
+ static const WCHAR search_fmt[] = {'%','s','\\','*',0};
+ static const WCHAR parent_fmt[] = {'%','s',',',' ',0};
+ static const WCHAR dblunder[] = {'_','_',0};
+ static const WCHAR fmt[] = {'V','e','r','s','i','o','n','=','%','s',',',' ',
+ 'C','u','l','t','u','r','e','=','n','e','u','t','r','a','l',',',' ',
+ 'P','u','b','l','i','c','K','e','y','T','o','k','e','n','=','%','s',0};
+ static const WCHAR ss_fmt[] = {'%','s','\\','%','s',0};
+
+ if (name)
+ parse_name(name, depth, path, buf);
+ else
+ sprintfW(buf, search_fmt, path);
+
+ hfind = FindFirstFileW(buf, &ffd);
+ if (hfind == INVALID_HANDLE_VALUE)
+ return S_OK;
+
+ do
+ {
+ if (!lstrcmpW(ffd.cFileName, dot) || !lstrcmpW(ffd.cFileName, dotdot))
+ continue;
+
+ if (depth == 0)
+ {
+ if (name)
+ ptr = strrchrW(buf, '\\') + 1;
+ else
+ ptr = ffd.cFileName;
+
+ sprintfW(parent, parent_fmt, ptr);
+ }
+ else if (depth == 1)
+ {
+ ptr = strstrW(ffd.cFileName, dblunder);
+ *ptr = '\0';
+ ptr += 2;
+ sprintfW(buf, fmt, ffd.cFileName, ptr);
+
+ lstrcpyW(disp, parent);
+ lstrcatW(disp, buf);
+
+ asmname = HeapAlloc(GetProcessHeap(), 0, sizeof(ASMNAME));
+ if (!asmname)
+ {
+ hr = E_OUTOFMEMORY;
+ break;
+ }
+
+ hr = CreateAssemblyNameObject(&asmname->name, disp,
+ CANOF_PARSE_DISPLAY_NAME, NULL);
+ if (FAILED(hr))
+ {
+ HeapFree(GetProcessHeap(), 0, asmname);
+ break;
+ }
+
+ list_add_tail(assemblies, &asmname->entry);
+ continue;
+ }
+
+ sprintfW(buf, ss_fmt, path, ffd.cFileName);
+ hr = enum_gac_assemblies(assemblies, name, depth + 1, buf);
+ if (FAILED(hr))
+ break;
+ } while (FindNextFileW(hfind, &ffd) != 0);
+
+ FindClose(hfind);
+ return hr;
+}
+
+static HRESULT enumerate_gac(IAssemblyEnumImpl *asmenum, IAssemblyName *pName)
+{
+ WCHAR path[MAX_PATH];
+ WCHAR buf[MAX_PATH];
+ HRESULT hr;
+ DWORD size;
+
+ static WCHAR under32[] = {'_','3','2',0};
+ static WCHAR msil[] = {'_','M','S','I','L',0};
+
+ size = MAX_PATH;
+ hr = GetCachePath(ASM_CACHE_GAC, buf, &size);
+ if (FAILED(hr))
+ return hr;
+
+ lstrcpyW(path, buf);
+ lstrcatW(path, under32);
+ hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, path);
+ if (FAILED(hr))
+ return hr;
+
+ lstrcpyW(path, buf);
+ lstrcatW(path, msil);
+ hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, path);
+ if (FAILED(hr))
+ return hr;
+
+ hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, buf);
+ if (FAILED(hr))
+ return hr;
+
+ return S_OK;
+}
+
+/******************************************************************
+ * CreateAssemblyEnum (FUSION.@)
+ */
+HRESULT WINAPI CreateAssemblyEnum(IAssemblyEnum **pEnum, IUnknown *pUnkReserved,
+ IAssemblyName *pName, DWORD dwFlags, LPVOID pvReserved)
+{
+ IAssemblyEnumImpl *asmenum;
+ HRESULT hr;
+
+ TRACE("(%p, %p, %p, %08x, %p)\n", pEnum, pUnkReserved,
+ pName, dwFlags, pvReserved);
+
+ if (!pEnum)
+ return E_INVALIDARG;
+
+ if (dwFlags == 0 || dwFlags == ASM_CACHE_ROOT)
+ return E_INVALIDARG;
+
+ asmenum = HeapAlloc(GetProcessHeap(), 0, sizeof(IAssemblyEnumImpl));
+ if (!asmenum)
+ return E_OUTOFMEMORY;
+
+ asmenum->lpIAssemblyEnumVtbl = &AssemblyEnumVtbl;
+ asmenum->ref = 1;
+ list_init(&asmenum->assemblies);
+
+ if (dwFlags & ASM_CACHE_GAC)
+ {
+ hr = enumerate_gac(asmenum, pName);
+ if (FAILED(hr))
+ {
+ HeapFree(GetProcessHeap(), 0, asmenum);
+ return hr;
+ }
+ }
+
+ asmenum->iter = list_head(&asmenum->assemblies);
+ *pEnum = (IAssemblyEnum *)asmenum;
+
+ return S_OK;
+}
diff --git a/dlls/fusion/asmname.c b/dlls/fusion/asmname.c
index 50ae05e..490de21 100644
--- a/dlls/fusion/asmname.c
+++ b/dlls/fusion/asmname.c
@@ -33,23 +33,10 @@
#include "wine/debug.h"
#include "wine/unicode.h"
+#include "fusionpriv.h"
WINE_DEFAULT_DEBUG_CHANNEL(fusion);
-static inline LPWSTR strdupW(LPCWSTR src)
-{
- LPWSTR dest;
-
- if (!src)
- return NULL;
-
- dest = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(src) + 1) * sizeof(WCHAR));
- if (dest)
- lstrcpyW(dest, src);
-
- return dest;
-}
-
typedef struct {
const IAssemblyNameVtbl *lpIAssemblyNameVtbl;
diff --git a/dlls/fusion/fusion.c b/dlls/fusion/fusion.c
index ac01cf4..5975d43 100644
--- a/dlls/fusion/fusion.c
+++ b/dlls/fusion/fusion.c
@@ -55,18 +55,6 @@ HRESULT WINAPI CompareAssemblyIdentity(LPCWSTR pwzAssemblyIdentity1, BOOL fUnifi
}
/******************************************************************
- * CreateAssemblyEnum (FUSION.@)
- */
-HRESULT WINAPI CreateAssemblyEnum(IAssemblyEnum **pEnum, IUnknown *pUnkReserved,
- IAssemblyName *pName, DWORD dwFlags, LPVOID pvReserved)
-{
- FIXME("(%p, %p, %p, %08x, %p) stub!\n", pEnum, pUnkReserved,
- pName, dwFlags, pvReserved);
-
- return E_NOTIMPL;
-}
-
-/******************************************************************
* CreateInstallReferenceEnum (FUSION.@)
*/
HRESULT WINAPI CreateInstallReferenceEnum(IInstallReferenceEnum **ppRefEnum,
diff --git a/dlls/fusion/fusionpriv.h b/dlls/fusion/fusionpriv.h
index a4e6193..848eab7 100644
--- a/dlls/fusion/fusionpriv.h
+++ b/dlls/fusion/fusionpriv.h
@@ -26,6 +26,7 @@
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
+#include "winver.h"
#include <pshpack1.h>
@@ -435,4 +436,18 @@ HRESULT assembly_get_version(ASSEMBLY *assembly, LPSTR *version);
HRESULT assembly_get_architecture(ASSEMBLY *assembly, DWORD fixme);
HRESULT assembly_get_pubkey_token(ASSEMBLY *assembly, LPSTR *token);
+static inline LPWSTR strdupW(LPCWSTR src)
+{
+ LPWSTR dest;
+
+ if (!src)
+ return NULL;
+
+ dest = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(src) + 1) * sizeof(WCHAR));
+ if (dest)
+ lstrcpyW(dest, src);
+
+ return dest;
+}
+
#endif /* __WINE_FUSION_PRIVATE__ */
More information about the wine-patches
mailing list