Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.

This commit is contained in:
Colin Finck 2017-10-03 07:45:34 +00:00
parent b94e2d8ca0
commit c2c66aff7d
24198 changed files with 0 additions and 37285 deletions

View file

@ -0,0 +1,30 @@
add_definitions(-D__WINESRC__)
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine)
spec2def(fusion.dll fusion.spec)
list(APPEND COMMON_SOURCE
asmcache.c
asmenum.c
asmname.c
assembly.c
fusion.c
fusionpriv.h
${CMAKE_CURRENT_BINARY_DIR}/fusion_stubs.c)
add_library(fusion_common STATIC ${COMMON_SOURCE})
add_dependencies(fusion_common psdk)
add_library(fusion SHARED
version.rc
${CMAKE_CURRENT_BINARY_DIR}/fusion.def)
set_module_type(fusion win32dll)
target_link_libraries(fusion fusion_common uuid wine)
add_importlibs(fusion advapi32 dbghelp shlwapi user32 msvcrt kernel32 ntdll)
add_pch(fusion_common fusionpriv.h COMMON_SOURCE)
add_cd_file(TARGET fusion DESTINATION reactos/Microsoft.NET/Framework/v1.0.3705 FOR all)
add_cd_file(TARGET fusion DESTINATION reactos/system32 FOR all)
add_subdirectory(fusion_1_1)
add_subdirectory(fusion_2_0)

649
dll/win32/fusion/asmcache.c Normal file
View file

@ -0,0 +1,649 @@
/*
* IAssemblyCache 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 "fusionpriv.h"
typedef struct {
IAssemblyCache IAssemblyCache_iface;
LONG ref;
HANDLE lock;
} IAssemblyCacheImpl;
typedef struct {
IAssemblyCacheItem IAssemblyCacheItem_iface;
LONG ref;
} IAssemblyCacheItemImpl;
static const WCHAR cache_mutex_nameW[] =
{'_','_','W','I','N','E','_','F','U','S','I','O','N','_','C','A','C','H','E','_','M','U','T','E','X','_','_',0};
static BOOL create_full_path(LPCWSTR path)
{
LPWSTR new_path;
BOOL ret = TRUE;
int len;
new_path = HeapAlloc(GetProcessHeap(), 0, (strlenW(path) + 1) * sizeof(WCHAR));
if (!new_path)
return FALSE;
strcpyW(new_path, path);
while ((len = strlenW(new_path)) && new_path[len - 1] == '\\')
new_path[len - 1] = 0;
while (!CreateDirectoryW(new_path, NULL))
{
LPWSTR slash;
DWORD last_error = GetLastError();
if(last_error == ERROR_ALREADY_EXISTS)
break;
if(last_error != ERROR_PATH_NOT_FOUND)
{
ret = FALSE;
break;
}
if(!(slash = strrchrW(new_path, '\\')))
{
ret = FALSE;
break;
}
len = slash - new_path;
new_path[len] = 0;
if(!create_full_path(new_path))
{
ret = FALSE;
break;
}
new_path[len] = '\\';
}
HeapFree(GetProcessHeap(), 0, new_path);
return ret;
}
static BOOL get_assembly_directory(LPWSTR dir, DWORD size, const char *version, PEKIND architecture)
{
static const WCHAR dotnet[] = {'\\','M','i','c','r','o','s','o','f','t','.','N','E','T','\\',0};
static const WCHAR gac[] = {'\\','a','s','s','e','m','b','l','y','\\','G','A','C',0};
static const WCHAR msil[] = {'_','M','S','I','L',0};
static const WCHAR x86[] = {'_','3','2',0};
static const WCHAR amd64[] = {'_','6','4',0};
DWORD len = GetWindowsDirectoryW(dir, size);
if (!strcmp(version, "v4.0.30319"))
{
strcpyW(dir + len, dotnet);
len += sizeof(dotnet)/sizeof(WCHAR) -1;
strcpyW(dir + len, gac + 1);
len += sizeof(gac)/sizeof(WCHAR) - 2;
}
else
{
strcpyW(dir + len, gac);
len += sizeof(gac)/sizeof(WCHAR) - 1;
}
switch (architecture)
{
case peNone:
break;
case peMSIL:
strcpyW(dir + len, msil);
break;
case peI386:
strcpyW(dir + len, x86);
break;
case peAMD64:
strcpyW(dir + len, amd64);
break;
default:
WARN("unhandled architecture %u\n", architecture);
return FALSE;
}
return TRUE;
}
/* IAssemblyCache */
static inline IAssemblyCacheImpl *impl_from_IAssemblyCache(IAssemblyCache *iface)
{
return CONTAINING_RECORD(iface, IAssemblyCacheImpl, IAssemblyCache_iface);
}
static HRESULT WINAPI IAssemblyCacheImpl_QueryInterface(IAssemblyCache *iface,
REFIID riid, LPVOID *ppobj)
{
IAssemblyCacheImpl *This = impl_from_IAssemblyCache(iface);
TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
*ppobj = NULL;
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IAssemblyCache))
{
IAssemblyCache_AddRef(iface);
*ppobj = &This->IAssemblyCache_iface;
return S_OK;
}
WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ppobj);
return E_NOINTERFACE;
}
static ULONG WINAPI IAssemblyCacheImpl_AddRef(IAssemblyCache *iface)
{
IAssemblyCacheImpl *This = impl_from_IAssemblyCache(iface);
ULONG refCount = InterlockedIncrement(&This->ref);
TRACE("(%p)->(ref before = %u)\n", This, refCount - 1);
return refCount;
}
static ULONG WINAPI IAssemblyCacheImpl_Release(IAssemblyCache *iface)
{
IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface);
ULONG refCount = InterlockedDecrement( &cache->ref );
TRACE("(%p)->(ref before = %u)\n", cache, refCount + 1);
if (!refCount)
{
CloseHandle( cache->lock );
HeapFree( GetProcessHeap(), 0, cache );
}
return refCount;
}
static void cache_lock( IAssemblyCacheImpl *cache )
{
WaitForSingleObject( cache->lock, INFINITE );
}
static void cache_unlock( IAssemblyCacheImpl *cache )
{
ReleaseMutex( cache->lock );
}
static HRESULT WINAPI IAssemblyCacheImpl_UninstallAssembly(IAssemblyCache *iface,
DWORD dwFlags,
LPCWSTR pszAssemblyName,
LPCFUSION_INSTALL_REFERENCE pRefData,
ULONG *pulDisposition)
{
HRESULT hr;
IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface);
IAssemblyName *asmname, *next = NULL;
IAssemblyEnum *asmenum = NULL;
WCHAR *p, *path = NULL;
ULONG disp;
DWORD len;
TRACE("(%p, 0%08x, %s, %p, %p)\n", iface, dwFlags,
debugstr_w(pszAssemblyName), pRefData, pulDisposition);
if (pRefData)
{
FIXME("application reference not supported\n");
return E_NOTIMPL;
}
hr = CreateAssemblyNameObject( &asmname, pszAssemblyName, CANOF_PARSE_DISPLAY_NAME, NULL );
if (FAILED( hr ))
return hr;
cache_lock( cache );
hr = CreateAssemblyEnum( &asmenum, NULL, asmname, ASM_CACHE_GAC, NULL );
if (FAILED( hr ))
goto done;
hr = IAssemblyEnum_GetNextAssembly( asmenum, NULL, &next, 0 );
if (hr == S_FALSE)
{
if (pulDisposition)
*pulDisposition = IASSEMBLYCACHE_UNINSTALL_DISPOSITION_ALREADY_UNINSTALLED;
goto done;
}
hr = IAssemblyName_GetPath( next, NULL, &len );
if (hr != HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ))
goto done;
if (!(path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
{
hr = E_OUTOFMEMORY;
goto done;
}
hr = IAssemblyName_GetPath( next, path, &len );
if (FAILED( hr ))
goto done;
if (DeleteFileW( path ))
{
if ((p = strrchrW( path, '\\' )))
{
*p = 0;
RemoveDirectoryW( path );
if ((p = strrchrW( path, '\\' )))
{
*p = 0;
RemoveDirectoryW( path );
}
}
disp = IASSEMBLYCACHE_UNINSTALL_DISPOSITION_UNINSTALLED;
hr = S_OK;
}
else
{
disp = IASSEMBLYCACHE_UNINSTALL_DISPOSITION_ALREADY_UNINSTALLED;
hr = S_FALSE;
}
if (pulDisposition) *pulDisposition = disp;
done:
IAssemblyName_Release( asmname );
if (next) IAssemblyName_Release( next );
if (asmenum) IAssemblyEnum_Release( asmenum );
HeapFree( GetProcessHeap(), 0, path );
cache_unlock( cache );
return hr;
}
static HRESULT WINAPI IAssemblyCacheImpl_QueryAssemblyInfo(IAssemblyCache *iface,
DWORD dwFlags,
LPCWSTR pszAssemblyName,
ASSEMBLY_INFO *pAsmInfo)
{
IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface);
IAssemblyName *asmname, *next = NULL;
IAssemblyEnum *asmenum = NULL;
HRESULT hr;
TRACE("(%p, %d, %s, %p)\n", iface, dwFlags,
debugstr_w(pszAssemblyName), pAsmInfo);
if (pAsmInfo)
{
if (pAsmInfo->cbAssemblyInfo == 0)
pAsmInfo->cbAssemblyInfo = sizeof(ASSEMBLY_INFO);
else if (pAsmInfo->cbAssemblyInfo != sizeof(ASSEMBLY_INFO))
return E_INVALIDARG;
}
hr = CreateAssemblyNameObject(&asmname, pszAssemblyName,
CANOF_PARSE_DISPLAY_NAME, NULL);
if (FAILED(hr))
return hr;
cache_lock( cache );
hr = CreateAssemblyEnum(&asmenum, NULL, asmname, ASM_CACHE_GAC, NULL);
if (FAILED(hr))
goto done;
for (;;)
{
hr = IAssemblyEnum_GetNextAssembly(asmenum, NULL, &next, 0);
if (hr != S_OK)
{
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
goto done;
}
hr = IAssemblyName_IsEqual(asmname, next, ASM_CMPF_IL_ALL);
if (hr == S_OK) break;
}
if (!pAsmInfo)
goto done;
hr = IAssemblyName_GetPath(next, pAsmInfo->pszCurrentAssemblyPathBuf, &pAsmInfo->cchBuf);
pAsmInfo->dwAssemblyFlags = ASSEMBLYINFO_FLAG_INSTALLED;
done:
IAssemblyName_Release(asmname);
if (next) IAssemblyName_Release(next);
if (asmenum) IAssemblyEnum_Release(asmenum);
cache_unlock( cache );
return hr;
}
static const IAssemblyCacheItemVtbl AssemblyCacheItemVtbl;
static HRESULT WINAPI IAssemblyCacheImpl_CreateAssemblyCacheItem(IAssemblyCache *iface,
DWORD dwFlags,
PVOID pvReserved,
IAssemblyCacheItem **ppAsmItem,
LPCWSTR pszAssemblyName)
{
IAssemblyCacheItemImpl *item;
FIXME("(%p, %d, %p, %p, %s) semi-stub!\n", iface, dwFlags, pvReserved,
ppAsmItem, debugstr_w(pszAssemblyName));
if (!ppAsmItem)
return E_INVALIDARG;
*ppAsmItem = NULL;
item = HeapAlloc(GetProcessHeap(), 0, sizeof(IAssemblyCacheItemImpl));
if (!item)
return E_OUTOFMEMORY;
item->IAssemblyCacheItem_iface.lpVtbl = &AssemblyCacheItemVtbl;
item->ref = 1;
*ppAsmItem = &item->IAssemblyCacheItem_iface;
return S_OK;
}
static HRESULT WINAPI IAssemblyCacheImpl_CreateAssemblyScavenger(IAssemblyCache *iface,
IUnknown **ppUnkReserved)
{
FIXME("(%p, %p) stub!\n", iface, ppUnkReserved);
return E_NOTIMPL;
}
static HRESULT copy_file( const WCHAR *src_dir, DWORD src_len, const WCHAR *dst_dir, DWORD dst_len,
const WCHAR *filename )
{
WCHAR *src_file, *dst_file;
DWORD len = strlenW( filename );
HRESULT hr = S_OK;
if (!(src_file = HeapAlloc( GetProcessHeap(), 0, (src_len + len + 1) * sizeof(WCHAR) )))
return E_OUTOFMEMORY;
memcpy( src_file, src_dir, src_len * sizeof(WCHAR) );
strcpyW( src_file + src_len, filename );
if (!(dst_file = HeapAlloc( GetProcessHeap(), 0, (dst_len + len + 1) * sizeof(WCHAR) )))
{
HeapFree( GetProcessHeap(), 0, src_file );
return E_OUTOFMEMORY;
}
memcpy( dst_file, dst_dir, dst_len * sizeof(WCHAR) );
strcpyW( dst_file + dst_len, filename );
if (!CopyFileW( src_file, dst_file, FALSE )) hr = HRESULT_FROM_WIN32( GetLastError() );
HeapFree( GetProcessHeap(), 0, src_file );
HeapFree( GetProcessHeap(), 0, dst_file );
return hr;
}
static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface,
DWORD dwFlags,
LPCWSTR pszManifestFilePath,
LPCFUSION_INSTALL_REFERENCE pRefData)
{
static const WCHAR format[] =
{'%','s','\\','%','s','\\','%','s','_','_','%','s','\\',0};
static const WCHAR format_v40[] =
{'%','s','\\','%','s','\\','v','4','.','0','_','%','s','_','_','%','s','\\',0};
static const WCHAR ext_exe[] = {'.','e','x','e',0};
static const WCHAR ext_dll[] = {'.','d','l','l',0};
IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface);
ASSEMBLY *assembly;
const WCHAR *extension, *filename, *src_dir;
WCHAR *name = NULL, *token = NULL, *version = NULL, *asmpath = NULL;
WCHAR asmdir[MAX_PATH], *p, **external_files = NULL, *dst_dir = NULL;
PEKIND architecture;
char *clr_version;
DWORD i, count = 0, src_len, dst_len = sizeof(format_v40)/sizeof(format_v40[0]);
HRESULT hr;
TRACE("(%p, %d, %s, %p)\n", iface, dwFlags,
debugstr_w(pszManifestFilePath), pRefData);
if (!pszManifestFilePath || !*pszManifestFilePath)
return E_INVALIDARG;
if (!(extension = strrchrW(pszManifestFilePath, '.')))
return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
if (lstrcmpiW(extension, ext_exe) && lstrcmpiW(extension, ext_dll))
return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
if (GetFileAttributesW(pszManifestFilePath) == INVALID_FILE_ATTRIBUTES)
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
hr = assembly_create(&assembly, pszManifestFilePath);
if (FAILED(hr))
{
hr = COR_E_ASSEMBLYEXPECTED;
goto done;
}
hr = assembly_get_name(assembly, &name);
if (FAILED(hr))
goto done;
hr = assembly_get_pubkey_token(assembly, &token);
if (FAILED(hr))
goto done;
hr = assembly_get_version(assembly, &version);
if (FAILED(hr))
goto done;
hr = assembly_get_runtime_version(assembly, &clr_version);
if (FAILED(hr))
goto done;
hr = assembly_get_external_files(assembly, &external_files, &count);
if (FAILED(hr))
goto done;
cache_lock( cache );
architecture = assembly_get_architecture(assembly);
get_assembly_directory(asmdir, MAX_PATH, clr_version, architecture);
dst_len += strlenW(asmdir) + strlenW(name) + strlenW(version) + strlenW(token);
if (!(dst_dir = HeapAlloc(GetProcessHeap(), 0, dst_len * sizeof(WCHAR))))
{
hr = E_OUTOFMEMORY;
goto done;
}
if (!strcmp(clr_version, "v4.0.30319"))
dst_len = sprintfW(dst_dir, format_v40, asmdir, name, version, token);
else
dst_len = sprintfW(dst_dir, format, asmdir, name, version, token);
create_full_path(dst_dir);
hr = assembly_get_path(assembly, &asmpath);
if (FAILED(hr))
goto done;
if ((p = strrchrW(asmpath, '\\')))
{
filename = p + 1;
src_dir = asmpath;
src_len = filename - asmpath;
}
else
{
filename = asmpath;
src_dir = NULL;
src_len = 0;
}
hr = copy_file(src_dir, src_len, dst_dir, dst_len, filename);
if (FAILED(hr))
goto done;
for (i = 0; i < count; i++)
{
hr = copy_file(src_dir, src_len, dst_dir, dst_len, external_files[i]);
if (FAILED(hr))
break;
}
done:
HeapFree(GetProcessHeap(), 0, name);
HeapFree(GetProcessHeap(), 0, token);
HeapFree(GetProcessHeap(), 0, version);
HeapFree(GetProcessHeap(), 0, asmpath);
HeapFree(GetProcessHeap(), 0, dst_dir);
for (i = 0; i < count; i++) HeapFree(GetProcessHeap(), 0, external_files[i]);
HeapFree(GetProcessHeap(), 0, external_files);
assembly_release(assembly);
cache_unlock( cache );
return hr;
}
static const IAssemblyCacheVtbl AssemblyCacheVtbl = {
IAssemblyCacheImpl_QueryInterface,
IAssemblyCacheImpl_AddRef,
IAssemblyCacheImpl_Release,
IAssemblyCacheImpl_UninstallAssembly,
IAssemblyCacheImpl_QueryAssemblyInfo,
IAssemblyCacheImpl_CreateAssemblyCacheItem,
IAssemblyCacheImpl_CreateAssemblyScavenger,
IAssemblyCacheImpl_InstallAssembly
};
/******************************************************************
* CreateAssemblyCache (FUSION.@)
*/
HRESULT WINAPI CreateAssemblyCache(IAssemblyCache **ppAsmCache, DWORD dwReserved)
{
IAssemblyCacheImpl *cache;
TRACE("(%p, %d)\n", ppAsmCache, dwReserved);
if (!ppAsmCache)
return E_INVALIDARG;
*ppAsmCache = NULL;
cache = HeapAlloc(GetProcessHeap(), 0, sizeof(IAssemblyCacheImpl));
if (!cache)
return E_OUTOFMEMORY;
cache->IAssemblyCache_iface.lpVtbl = &AssemblyCacheVtbl;
cache->ref = 1;
cache->lock = CreateMutexW( NULL, FALSE, cache_mutex_nameW );
if (!cache->lock)
{
HeapFree( GetProcessHeap(), 0, cache );
return HRESULT_FROM_WIN32( GetLastError() );
}
*ppAsmCache = &cache->IAssemblyCache_iface;
return S_OK;
}
/* IAssemblyCacheItem */
static inline IAssemblyCacheItemImpl *impl_from_IAssemblyCacheItem(IAssemblyCacheItem *iface)
{
return CONTAINING_RECORD(iface, IAssemblyCacheItemImpl, IAssemblyCacheItem_iface);
}
static HRESULT WINAPI IAssemblyCacheItemImpl_QueryInterface(IAssemblyCacheItem *iface,
REFIID riid, LPVOID *ppobj)
{
IAssemblyCacheItemImpl *This = impl_from_IAssemblyCacheItem(iface);
TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
*ppobj = NULL;
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IAssemblyCacheItem))
{
IAssemblyCacheItem_AddRef(iface);
*ppobj = &This->IAssemblyCacheItem_iface;
return S_OK;
}
WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ppobj);
return E_NOINTERFACE;
}
static ULONG WINAPI IAssemblyCacheItemImpl_AddRef(IAssemblyCacheItem *iface)
{
IAssemblyCacheItemImpl *This = impl_from_IAssemblyCacheItem(iface);
ULONG refCount = InterlockedIncrement(&This->ref);
TRACE("(%p)->(ref before = %u)\n", This, refCount - 1);
return refCount;
}
static ULONG WINAPI IAssemblyCacheItemImpl_Release(IAssemblyCacheItem *iface)
{
IAssemblyCacheItemImpl *This = impl_from_IAssemblyCacheItem(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 IAssemblyCacheItemImpl_CreateStream(IAssemblyCacheItem *iface,
DWORD dwFlags,
LPCWSTR pszStreamName,
DWORD dwFormat,
DWORD dwFormatFlags,
IStream **ppIStream,
ULARGE_INTEGER *puliMaxSize)
{
FIXME("(%p, %d, %s, %d, %d, %p, %p) stub!\n", iface, dwFlags,
debugstr_w(pszStreamName), dwFormat, dwFormatFlags, ppIStream, puliMaxSize);
return E_NOTIMPL;
}
static HRESULT WINAPI IAssemblyCacheItemImpl_Commit(IAssemblyCacheItem *iface,
DWORD dwFlags,
ULONG *pulDisposition)
{
FIXME("(%p, %d, %p) stub!\n", iface, dwFlags, pulDisposition);
return E_NOTIMPL;
}
static HRESULT WINAPI IAssemblyCacheItemImpl_AbortItem(IAssemblyCacheItem *iface)
{
FIXME("(%p) stub!\n", iface);
return E_NOTIMPL;
}
static const IAssemblyCacheItemVtbl AssemblyCacheItemVtbl = {
IAssemblyCacheItemImpl_QueryInterface,
IAssemblyCacheItemImpl_AddRef,
IAssemblyCacheItemImpl_Release,
IAssemblyCacheItemImpl_CreateStream,
IAssemblyCacheItemImpl_Commit,
IAssemblyCacheItemImpl_AbortItem
};

485
dll/win32/fusion/asmenum.c Normal file
View file

@ -0,0 +1,485 @@
/*
* 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 "fusionpriv.h"
#include <wine/list.h>
typedef struct _tagASMNAME
{
struct list entry;
IAssemblyName *name;
} ASMNAME;
typedef struct
{
IAssemblyEnum IAssemblyEnum_iface;
struct list assemblies;
struct list *iter;
LONG ref;
} IAssemblyEnumImpl;
static inline IAssemblyEnumImpl *impl_from_IAssemblyEnum(IAssemblyEnum *iface)
{
return CONTAINING_RECORD(iface, IAssemblyEnumImpl, IAssemblyEnum_iface);
}
static HRESULT WINAPI IAssemblyEnumImpl_QueryInterface(IAssemblyEnum *iface,
REFIID riid, LPVOID *ppobj)
{
IAssemblyEnumImpl *This = impl_from_IAssemblyEnum(iface);
TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
*ppobj = NULL;
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IAssemblyEnum))
{
IAssemblyEnum_AddRef(iface);
*ppobj = &This->IAssemblyEnum_iface;
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 = impl_from_IAssemblyEnum(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 = impl_from_IAssemblyEnum(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 = impl_from_IAssemblyEnum(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 = impl_from_IAssemblyEnum(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 build_file_mask(IAssemblyName *name, int depth, const WCHAR *path,
const WCHAR *prefix, WCHAR *buf)
{
static const WCHAR star[] = {'*',0};
static const WCHAR ss_fmt[] = {'%','s','\\','%','s',0};
static const WCHAR sss_fmt[] = {'%','s','\\','%','s','_','_','%','s',0};
static const WCHAR ssss_fmt[] = {'%','s','\\','%','s','%','s','_','_','%','s',0};
static const WCHAR ver_fmt[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
static const WCHAR star_fmt[] = {'%','s','\\','*',0};
static const WCHAR star_prefix_fmt[] = {'%','s','\\','%','s','*',0};
WCHAR disp[MAX_PATH], version[24]; /* strlen("65535") * 4 + 3 + 1 */
LPCWSTR verptr, pubkeyptr;
HRESULT hr;
DWORD size, major_size, minor_size, build_size, revision_size;
WORD major, minor, build, revision;
WCHAR token_str[TOKEN_LENGTH + 1];
BYTE token[BYTES_PER_TOKEN];
if (!name)
{
if (prefix && depth == 1)
sprintfW(buf, star_prefix_fmt, path, prefix);
else
sprintfW(buf, star_fmt, path);
return;
}
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)
{
major_size = sizeof(major);
IAssemblyName_GetProperty(name, ASM_NAME_MAJOR_VERSION, &major, &major_size);
minor_size = sizeof(minor);
IAssemblyName_GetProperty(name, ASM_NAME_MINOR_VERSION, &minor, &minor_size);
build_size = sizeof(build);
IAssemblyName_GetProperty(name, ASM_NAME_BUILD_NUMBER, &build, &build_size);
revision_size = sizeof(revision);
IAssemblyName_GetProperty(name, ASM_NAME_REVISION_NUMBER, &revision, &revision_size);
if (!major_size || !minor_size || !build_size || !revision_size) verptr = star;
else
{
sprintfW(version, ver_fmt, major, minor, build, revision);
verptr = version;
}
size = sizeof(token);
IAssemblyName_GetProperty(name, ASM_NAME_PUBLIC_KEY_TOKEN, token, &size);
if (!size) pubkeyptr = star;
else
{
token_to_str(token, token_str);
pubkeyptr = token_str;
}
if (prefix)
sprintfW(buf, ssss_fmt, path, prefix, verptr, pubkeyptr);
else
sprintfW(buf, sss_fmt, path, verptr, pubkeyptr);
}
}
static int compare_assembly_names(ASMNAME *asmname1, ASMNAME *asmname2)
{
int ret;
WORD version1, version2;
WCHAR name1[MAX_PATH], name2[MAX_PATH];
WCHAR token_str1[TOKEN_LENGTH + 1], token_str2[TOKEN_LENGTH + 1];
BYTE token1[BYTES_PER_TOKEN], token2[BYTES_PER_TOKEN];
DWORD size, i;
size = sizeof(name1);
IAssemblyName_GetProperty(asmname1->name, ASM_NAME_NAME, name1, &size);
size = sizeof(name2);
IAssemblyName_GetProperty(asmname2->name, ASM_NAME_NAME, name2, &size);
if ((ret = strcmpiW(name1, name2))) return ret;
for (i = ASM_NAME_MAJOR_VERSION; i < ASM_NAME_CULTURE; i++)
{
size = sizeof(version1);
IAssemblyName_GetProperty(asmname1->name, i, &version1, &size);
size = sizeof(version2);
IAssemblyName_GetProperty(asmname2->name, i, &version2, &size);
if (version1 < version2) return -1;
if (version1 > version2) return 1;
}
/* FIXME: compare cultures */
size = sizeof(token1);
IAssemblyName_GetProperty(asmname1->name, ASM_NAME_PUBLIC_KEY_TOKEN, token1, &size);
size = sizeof(token2);
IAssemblyName_GetProperty(asmname2->name, ASM_NAME_PUBLIC_KEY_TOKEN, token2, &size);
token_to_str(token1, token_str1);
token_to_str(token2, token_str2);
if ((ret = strcmpiW(token_str1, token_str2))) return ret;
return 0;
}
/* insert assembly in list preserving sort order */
static void insert_assembly(struct list *assemblies, ASMNAME *to_insert)
{
struct list *item;
LIST_FOR_EACH(item, assemblies)
{
ASMNAME *name = LIST_ENTRY(item, ASMNAME, entry);
if (compare_assembly_names(name, to_insert) > 0)
{
list_add_before(&name->entry, &to_insert->entry);
return;
}
}
list_add_tail(assemblies, &to_insert->entry);
}
static HRESULT enum_gac_assemblies(struct list *assemblies, IAssemblyName *name,
int depth, const WCHAR *prefix, LPWSTR path)
{
static const WCHAR dot[] = {'.',0};
static const WCHAR dotdot[] = {'.','.',0};
static const WCHAR dblunder[] = {'_','_',0};
static const WCHAR path_fmt[] = {'%','s','\\','%','s','\\','%','s','.','d','l','l',0};
static const WCHAR name_fmt[] = {'%','s',',',' ','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};
WIN32_FIND_DATAW ffd;
WCHAR buf[MAX_PATH], disp[MAX_PATH], asmpath[MAX_PATH], *ptr;
static WCHAR parent[MAX_PATH];
ASMNAME *asmname;
HANDLE hfind;
HRESULT hr = S_OK;
build_file_mask(name, depth, path, prefix, buf);
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;
lstrcpyW(parent, ptr);
}
else if (depth == 1)
{
const WCHAR *token, *version = ffd.cFileName;
sprintfW(asmpath, path_fmt, path, ffd.cFileName, parent);
ptr = strstrW(ffd.cFileName, dblunder);
*ptr = '\0';
token = ptr + 2;
if (prefix)
{
unsigned int prefix_len = strlenW(prefix);
if (strlenW(ffd.cFileName) >= prefix_len &&
!memicmpW(ffd.cFileName, prefix, prefix_len))
version += prefix_len;
}
sprintfW(disp, name_fmt, parent, version, token);
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;
}
hr = IAssemblyName_SetPath(asmname->name, asmpath);
if (FAILED(hr))
{
IAssemblyName_Release(asmname->name);
HeapFree(GetProcessHeap(), 0, asmname);
break;
}
insert_assembly(assemblies, asmname);
continue;
}
sprintfW(buf, ss_fmt, path, ffd.cFileName);
hr = enum_gac_assemblies(assemblies, name, depth + 1, prefix, buf);
if (FAILED(hr))
break;
} while (FindNextFileW(hfind, &ffd) != 0);
FindClose(hfind);
return hr;
}
static HRESULT enumerate_gac(IAssemblyEnumImpl *asmenum, IAssemblyName *pName)
{
static const WCHAR gac[] = {'\\','G','A','C',0};
static const WCHAR gac_32[] = {'\\','G','A','C','_','3','2',0};
static const WCHAR gac_64[] = {'\\','G','A','C','_','6','4',0};
static const WCHAR gac_msil[] = {'\\','G','A','C','_','M','S','I','L',0};
static const WCHAR v40[] = {'v','4','.','0','_',0};
WCHAR path[MAX_PATH], buf[MAX_PATH];
SYSTEM_INFO info;
HRESULT hr;
DWORD size;
size = MAX_PATH;
hr = GetCachePath(ASM_CACHE_ROOT_EX, buf, &size);
if (FAILED(hr))
return hr;
strcpyW(path, buf);
GetNativeSystemInfo(&info);
if (info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
{
strcpyW(path + size - 1, gac_64);
hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, v40, path);
if (FAILED(hr))
return hr;
}
strcpyW(path + size - 1, gac_32);
hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, v40, path);
if (FAILED(hr))
return hr;
strcpyW(path + size - 1, gac_msil);
hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, v40, path);
if (FAILED(hr))
return hr;
size = MAX_PATH;
hr = GetCachePath(ASM_CACHE_ROOT, buf, &size);
if (FAILED(hr))
return hr;
strcpyW(path, buf);
if (info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
{
strcpyW(path + size - 1, gac_64);
hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, NULL, path);
if (FAILED(hr))
return hr;
}
strcpyW(path + size - 1, gac_32);
hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, NULL, path);
if (FAILED(hr))
return hr;
strcpyW(path + size - 1, gac_msil);
hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, NULL, path);
if (FAILED(hr))
return hr;
strcpyW(path + size - 1, gac);
hr = enum_gac_assemblies(&asmenum->assemblies, pName, 0, NULL, path);
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->IAssemblyEnum_iface.lpVtbl = &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 = &asmenum->IAssemblyEnum_iface;
return S_OK;
}

749
dll/win32/fusion/asmname.c Normal file
View file

@ -0,0 +1,749 @@
/*
* IAssemblyName 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 "fusionpriv.h"
#include <assert.h>
#include <winuser.h>
typedef struct {
IAssemblyName IAssemblyName_iface;
LPWSTR path;
LPWSTR displayname;
LPWSTR name;
LPWSTR culture;
LPWSTR procarch;
WORD version[4];
DWORD versize;
BYTE pubkey[8];
BOOL haspubkey;
LONG ref;
} IAssemblyNameImpl;
static const WCHAR separator[] = {',',' ',0};
static const WCHAR version[] = {'V','e','r','s','i','o','n',0};
static const WCHAR culture[] = {'C','u','l','t','u','r','e',0};
static const WCHAR pubkey[] =
{'P','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
static const WCHAR procarch[] = {'p','r','o','c','e','s','s','o','r',
'A','r','c','h','i','t','e','c','t','u','r','e',0};
#define CHARS_PER_PUBKEY 16
static inline IAssemblyNameImpl *impl_from_IAssemblyName(IAssemblyName *iface)
{
return CONTAINING_RECORD(iface, IAssemblyNameImpl, IAssemblyName_iface);
}
static HRESULT WINAPI IAssemblyNameImpl_QueryInterface(IAssemblyName *iface,
REFIID riid, LPVOID *ppobj)
{
IAssemblyNameImpl *This = impl_from_IAssemblyName(iface);
TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
*ppobj = NULL;
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IAssemblyName))
{
IAssemblyName_AddRef(iface);
*ppobj = &This->IAssemblyName_iface;
return S_OK;
}
WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ppobj);
return E_NOINTERFACE;
}
static ULONG WINAPI IAssemblyNameImpl_AddRef(IAssemblyName *iface)
{
IAssemblyNameImpl *This = impl_from_IAssemblyName(iface);
ULONG refCount = InterlockedIncrement(&This->ref);
TRACE("(%p)->(ref before = %u)\n", This, refCount - 1);
return refCount;
}
static ULONG WINAPI IAssemblyNameImpl_Release(IAssemblyName *iface)
{
IAssemblyNameImpl *This = impl_from_IAssemblyName(iface);
ULONG refCount = InterlockedDecrement(&This->ref);
TRACE("(%p)->(ref before = %u)\n", This, refCount + 1);
if (!refCount)
{
HeapFree(GetProcessHeap(), 0, This->path);
HeapFree(GetProcessHeap(), 0, This->displayname);
HeapFree(GetProcessHeap(), 0, This->name);
HeapFree(GetProcessHeap(), 0, This->culture);
HeapFree(GetProcessHeap(), 0, This->procarch);
HeapFree(GetProcessHeap(), 0, This);
}
return refCount;
}
static HRESULT WINAPI IAssemblyNameImpl_SetProperty(IAssemblyName *iface,
DWORD PropertyId,
LPVOID pvProperty,
DWORD cbProperty)
{
FIXME("(%p, %d, %p, %d) stub!\n", iface, PropertyId, pvProperty, cbProperty);
return E_NOTIMPL;
}
static HRESULT WINAPI IAssemblyNameImpl_GetProperty(IAssemblyName *iface,
DWORD PropertyId,
LPVOID pvProperty,
LPDWORD pcbProperty)
{
IAssemblyNameImpl *name = impl_from_IAssemblyName(iface);
TRACE("(%p, %d, %p, %p)\n", iface, PropertyId, pvProperty, pcbProperty);
*((LPWSTR)pvProperty) = '\0';
switch (PropertyId)
{
case ASM_NAME_NULL_PUBLIC_KEY:
case ASM_NAME_NULL_PUBLIC_KEY_TOKEN:
if (name->haspubkey)
return S_OK;
return S_FALSE;
case ASM_NAME_NULL_CUSTOM:
return S_OK;
case ASM_NAME_NAME:
*pcbProperty = 0;
if (name->name)
{
lstrcpyW(pvProperty, name->name);
*pcbProperty = (lstrlenW(name->name) + 1) * 2;
}
break;
case ASM_NAME_MAJOR_VERSION:
*pcbProperty = 0;
*((WORD *)pvProperty) = name->version[0];
if (name->versize >= 1)
*pcbProperty = sizeof(WORD);
break;
case ASM_NAME_MINOR_VERSION:
*pcbProperty = 0;
*((WORD *)pvProperty) = name->version[1];
if (name->versize >= 2)
*pcbProperty = sizeof(WORD);
break;
case ASM_NAME_BUILD_NUMBER:
*pcbProperty = 0;
*((WORD *)pvProperty) = name->version[2];
if (name->versize >= 3)
*pcbProperty = sizeof(WORD);
break;
case ASM_NAME_REVISION_NUMBER:
*pcbProperty = 0;
*((WORD *)pvProperty) = name->version[3];
if (name->versize >= 4)
*pcbProperty = sizeof(WORD);
break;
case ASM_NAME_CULTURE:
*pcbProperty = 0;
if (name->culture)
{
lstrcpyW(pvProperty, name->culture);
*pcbProperty = (lstrlenW(name->culture) + 1) * 2;
}
break;
case ASM_NAME_PUBLIC_KEY_TOKEN:
*pcbProperty = 0;
if (name->haspubkey)
{
memcpy(pvProperty, name->pubkey, sizeof(DWORD) * 2);
*pcbProperty = sizeof(DWORD) * 2;
}
break;
default:
*pcbProperty = 0;
break;
}
return S_OK;
}
static HRESULT WINAPI IAssemblyNameImpl_Finalize(IAssemblyName *iface)
{
FIXME("(%p) stub!\n", iface);
return E_NOTIMPL;
}
static HRESULT WINAPI IAssemblyNameImpl_GetDisplayName(IAssemblyName *iface,
LPOLESTR szDisplayName,
LPDWORD pccDisplayName,
DWORD dwDisplayFlags)
{
static const WCHAR equals[] = {'=',0};
IAssemblyNameImpl *name = impl_from_IAssemblyName(iface);
WCHAR verstr[30], *cultureval = NULL;
DWORD size;
TRACE("(%p, %p, %p, %d)\n", iface, szDisplayName,
pccDisplayName, dwDisplayFlags);
if (dwDisplayFlags == 0)
{
if (!name->displayname || !*name->displayname)
return FUSION_E_INVALID_NAME;
size = strlenW(name->displayname) + 1;
if (*pccDisplayName < size)
{
*pccDisplayName = size;
return E_NOT_SUFFICIENT_BUFFER;
}
if (szDisplayName) strcpyW(szDisplayName, name->displayname);
*pccDisplayName = size;
return S_OK;
}
if (!name->name || !*name->name)
return FUSION_E_INVALID_NAME;
/* Verify buffer size is sufficient */
size = lstrlenW(name->name) + 1;
if ((dwDisplayFlags & ASM_DISPLAYF_VERSION) && (name->versize > 0))
{
static const WCHAR spec[] = {'%','d',0};
static const WCHAR period[] = {'.',0};
DWORD i;
wsprintfW(verstr, spec, name->version[0]);
for (i = 1; i < name->versize; i++)
{
WCHAR value[6];
wsprintfW(value, spec, name->version[i]);
lstrcatW(verstr, period);
lstrcatW(verstr, value);
}
size += lstrlenW(separator) + lstrlenW(version) + lstrlenW(equals) + lstrlenW(verstr);
}
if ((dwDisplayFlags & ASM_DISPLAYF_CULTURE) && (name->culture))
{
static const WCHAR neutral[] = {'n','e','u','t','r','a','l', 0};
cultureval = (lstrlenW(name->culture) == 2) ? name->culture : (LPWSTR) neutral;
size += lstrlenW(separator) + lstrlenW(culture) + lstrlenW(equals) + lstrlenW(cultureval);
}
if ((dwDisplayFlags & ASM_DISPLAYF_PUBLIC_KEY_TOKEN) && (name->haspubkey))
size += lstrlenW(separator) + lstrlenW(pubkey) + lstrlenW(equals) + CHARS_PER_PUBKEY;
if ((dwDisplayFlags & ASM_DISPLAYF_PROCESSORARCHITECTURE) && (name->procarch))
size += lstrlenW(separator) + lstrlenW(procarch) + lstrlenW(equals) + lstrlenW(name->procarch);
if (size > *pccDisplayName)
return S_FALSE;
/* Construct the string */
lstrcpyW(szDisplayName, name->name);
if ((dwDisplayFlags & ASM_DISPLAYF_VERSION) && (name->versize > 0))
{
lstrcatW(szDisplayName, separator);
lstrcatW(szDisplayName, version);
lstrcatW(szDisplayName, equals);
lstrcatW(szDisplayName, verstr);
}
if ((dwDisplayFlags & ASM_DISPLAYF_CULTURE) && (name->culture))
{
lstrcatW(szDisplayName, separator);
lstrcatW(szDisplayName, culture);
lstrcatW(szDisplayName, equals);
lstrcatW(szDisplayName, cultureval);
}
if ((dwDisplayFlags & ASM_DISPLAYF_PUBLIC_KEY_TOKEN) && (name->haspubkey))
{
WCHAR pkt[CHARS_PER_PUBKEY + 1];
static const WCHAR spec[] = {'%','0','x','%','0','x','%','0','x',
'%','0','x','%','0','x','%','0','x','%','0','x','%','0','x',0};
lstrcatW(szDisplayName, separator);
lstrcatW(szDisplayName, pubkey);
lstrcatW(szDisplayName, equals);
wsprintfW(pkt, spec, name->pubkey[0], name->pubkey[1], name->pubkey[2],
name->pubkey[3], name->pubkey[4], name->pubkey[5], name->pubkey[6],
name->pubkey[7]);
lstrcatW(szDisplayName, pkt);
}
if ((dwDisplayFlags & ASM_DISPLAYF_PROCESSORARCHITECTURE) && (name->procarch))
{
lstrcatW(szDisplayName, separator);
lstrcatW(szDisplayName, procarch);
lstrcatW(szDisplayName, equals);
lstrcatW(szDisplayName, name->procarch);
}
*pccDisplayName = size;
return S_OK;
}
static HRESULT WINAPI IAssemblyNameImpl_Reserved(IAssemblyName *iface,
REFIID refIID,
IUnknown *pUnkReserved1,
IUnknown *pUnkReserved2,
LPCOLESTR szReserved,
LONGLONG llReserved,
LPVOID pvReserved,
DWORD cbReserved,
LPVOID *ppReserved)
{
TRACE("(%p, %s, %p, %p, %s, %s, %p, %d, %p)\n", iface,
debugstr_guid(refIID), pUnkReserved1, pUnkReserved2,
debugstr_w(szReserved), wine_dbgstr_longlong(llReserved),
pvReserved, cbReserved, ppReserved);
return E_NOTIMPL;
}
static HRESULT WINAPI IAssemblyNameImpl_GetName(IAssemblyName *iface,
LPDWORD lpcwBuffer,
WCHAR *pwzName)
{
IAssemblyNameImpl *name = impl_from_IAssemblyName(iface);
DWORD len;
TRACE("(%p, %p, %p)\n", iface, lpcwBuffer, pwzName);
if (name->name)
len = strlenW(name->name) + 1;
else
len = 0;
if (*lpcwBuffer < len)
{
*lpcwBuffer = len;
return E_NOT_SUFFICIENT_BUFFER;
}
if (!name->name) lpcwBuffer[0] = 0;
else strcpyW(pwzName, name->name);
*lpcwBuffer = len;
return S_OK;
}
static HRESULT WINAPI IAssemblyNameImpl_GetVersion(IAssemblyName *iface,
LPDWORD pdwVersionHi,
LPDWORD pdwVersionLow)
{
IAssemblyNameImpl *name = impl_from_IAssemblyName(iface);
TRACE("(%p, %p, %p)\n", iface, pdwVersionHi, pdwVersionLow);
*pdwVersionHi = 0;
*pdwVersionLow = 0;
if (name->versize != 4)
return FUSION_E_INVALID_NAME;
*pdwVersionHi = (name->version[0] << 16) + name->version[1];
*pdwVersionLow = (name->version[2] << 16) + name->version[3];
return S_OK;
}
static HRESULT WINAPI IAssemblyNameImpl_IsEqual(IAssemblyName *iface,
IAssemblyName *pName,
DWORD flags)
{
IAssemblyNameImpl *name1 = impl_from_IAssemblyName(iface);
IAssemblyNameImpl *name2 = impl_from_IAssemblyName(pName);
TRACE("(%p, %p, 0x%08x)\n", iface, pName, flags);
if (!pName) return S_FALSE;
if (flags & ~ASM_CMPF_IL_ALL) FIXME("unsupported flags\n");
if ((flags & ASM_CMPF_NAME) && strcmpW(name1->name, name2->name)) return S_FALSE;
if (name1->versize && name2->versize)
{
if ((flags & ASM_CMPF_MAJOR_VERSION) &&
name1->version[0] != name2->version[0]) return S_FALSE;
if ((flags & ASM_CMPF_MINOR_VERSION) &&
name1->version[1] != name2->version[1]) return S_FALSE;
if ((flags & ASM_CMPF_BUILD_NUMBER) &&
name1->version[2] != name2->version[2]) return S_FALSE;
if ((flags & ASM_CMPF_REVISION_NUMBER) &&
name1->version[3] != name2->version[3]) return S_FALSE;
}
if ((flags & ASM_CMPF_PUBLIC_KEY_TOKEN) &&
name1->haspubkey && name2->haspubkey &&
memcmp(name1->pubkey, name2->pubkey, sizeof(name1->pubkey))) return S_FALSE;
if ((flags & ASM_CMPF_CULTURE) &&
name1->culture && name2->culture &&
strcmpW(name1->culture, name2->culture)) return S_FALSE;
return S_OK;
}
static HRESULT WINAPI IAssemblyNameImpl_Clone(IAssemblyName *iface,
IAssemblyName **pName)
{
FIXME("(%p, %p) stub!\n", iface, pName);
return E_NOTIMPL;
}
static const IAssemblyNameVtbl AssemblyNameVtbl = {
IAssemblyNameImpl_QueryInterface,
IAssemblyNameImpl_AddRef,
IAssemblyNameImpl_Release,
IAssemblyNameImpl_SetProperty,
IAssemblyNameImpl_GetProperty,
IAssemblyNameImpl_Finalize,
IAssemblyNameImpl_GetDisplayName,
IAssemblyNameImpl_Reserved,
IAssemblyNameImpl_GetName,
IAssemblyNameImpl_GetVersion,
IAssemblyNameImpl_IsEqual,
IAssemblyNameImpl_Clone
};
/* Internal methods */
static inline IAssemblyNameImpl *unsafe_impl_from_IAssemblyName(IAssemblyName *iface)
{
assert(iface->lpVtbl == &AssemblyNameVtbl);
return impl_from_IAssemblyName(iface);
}
HRESULT IAssemblyName_SetPath(IAssemblyName *iface, LPCWSTR path)
{
IAssemblyNameImpl *name = unsafe_impl_from_IAssemblyName(iface);
name->path = strdupW(path);
if (!name->path)
return E_OUTOFMEMORY;
return S_OK;
}
HRESULT IAssemblyName_GetPath(IAssemblyName *iface, LPWSTR buf, ULONG *len)
{
ULONG buffer_size = *len;
IAssemblyNameImpl *name = unsafe_impl_from_IAssemblyName(iface);
if (!name->path)
return S_OK;
if (!buf)
buffer_size = 0;
*len = lstrlenW(name->path) + 1;
if (*len <= buffer_size)
lstrcpyW(buf, name->path);
else
return E_NOT_SUFFICIENT_BUFFER;
return S_OK;
}
static HRESULT parse_version(IAssemblyNameImpl *name, LPWSTR version)
{
LPWSTR beg, end;
int i;
for (i = 0, beg = version; i < 4; i++)
{
if (!*beg)
return S_OK;
end = strchrW(beg, '.');
if (end) *end = '\0';
name->version[i] = atolW(beg);
name->versize++;
if (!end && i < 3)
return S_OK;
beg = end + 1;
}
return S_OK;
}
static HRESULT parse_culture(IAssemblyNameImpl *name, LPCWSTR culture)
{
static const WCHAR empty[] = {0};
if (lstrlenW(culture) == 2)
name->culture = strdupW(culture);
else
name->culture = strdupW(empty);
return S_OK;
}
static BOOL is_hex(WCHAR c)
{
return ((c >= 'a' && c <= 'f') ||
(c >= 'A' && c <= 'F') ||
(c >= '0' && c <= '9'));
}
static BYTE hextobyte(WCHAR c)
{
if(c >= '0' && c <= '9')
return c - '0';
if(c >= 'A' && c <= 'F')
return c - 'A' + 10;
if(c >= 'a' && c <= 'f')
return c - 'a' + 10;
return 0;
}
static HRESULT parse_pubkey(IAssemblyNameImpl *name, LPCWSTR pubkey)
{
int i;
BYTE val;
static const WCHAR nullstr[] = {'n','u','l','l',0};
if(lstrcmpiW(pubkey, nullstr) == 0)
return FUSION_E_PRIVATE_ASM_DISALLOWED;
if (lstrlenW(pubkey) < CHARS_PER_PUBKEY)
return FUSION_E_INVALID_NAME;
for (i = 0; i < CHARS_PER_PUBKEY; i++)
if (!is_hex(pubkey[i]))
return FUSION_E_INVALID_NAME;
name->haspubkey = TRUE;
for (i = 0; i < CHARS_PER_PUBKEY; i += 2)
{
val = (hextobyte(pubkey[i]) << 4) + hextobyte(pubkey[i + 1]);
name->pubkey[i / 2] = val;
}
return S_OK;
}
static WCHAR *parse_value( const WCHAR *str, unsigned int len )
{
WCHAR *ret;
const WCHAR *p = str;
BOOL quoted = FALSE;
unsigned int i = 0;
if (!(ret = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return NULL;
if (*p == '\"')
{
quoted = TRUE;
p++;
}
while (*p && *p != '\"') ret[i++] = *p++;
if ((quoted && *p != '\"') || (!quoted && *p == '\"'))
{
HeapFree( GetProcessHeap(), 0, ret );
return NULL;
}
ret[i] = 0;
return ret;
}
static HRESULT parse_display_name(IAssemblyNameImpl *name, LPCWSTR szAssemblyName)
{
LPWSTR str, save, ptr, ptr2, value;
HRESULT hr = S_OK;
BOOL done = FALSE;
if (!szAssemblyName)
return S_OK;
name->displayname = strdupW(szAssemblyName);
if (!name->displayname)
return E_OUTOFMEMORY;
str = strdupW(szAssemblyName);
save = str;
if (!str)
{
hr = E_OUTOFMEMORY;
goto done;
}
ptr = strchrW(str, ',');
if (ptr) *ptr = '\0';
/* no ',' but ' ' only */
if( !ptr && strchrW(str, ' ') )
{
hr = FUSION_E_INVALID_NAME;
goto done;
}
name->name = strdupW(str);
if (!name->name)
{
hr = E_OUTOFMEMORY;
goto done;
}
if (!ptr)
goto done;
str = ptr + 1;
while (!done)
{
ptr = strchrW(str, '=');
if (!ptr)
{
hr = FUSION_E_INVALID_NAME;
goto done;
}
*(ptr++) = '\0';
if (!*ptr)
{
hr = FUSION_E_INVALID_NAME;
goto done;
}
if (!(ptr2 = strchrW(ptr, ',')))
{
if (!(ptr2 = strchrW(ptr, '\0')))
{
hr = FUSION_E_INVALID_NAME;
goto done;
}
done = TRUE;
}
*ptr2 = '\0';
if (!(value = parse_value( ptr, ptr2 - ptr )))
{
hr = FUSION_E_INVALID_NAME;
goto done;
}
while (*str == ' ') str++;
if (!lstrcmpiW(str, version))
hr = parse_version( name, value );
else if (!lstrcmpiW(str, culture))
hr = parse_culture( name, value );
else if (!lstrcmpiW(str, pubkey))
hr = parse_pubkey( name, value );
else if (!lstrcmpiW(str, procarch))
{
name->procarch = value;
value = NULL;
}
HeapFree( GetProcessHeap(), 0, value );
if (FAILED(hr))
goto done;
str = ptr2 + 1;
}
done:
HeapFree(GetProcessHeap(), 0, save);
if (FAILED(hr))
{
HeapFree(GetProcessHeap(), 0, name->displayname);
HeapFree(GetProcessHeap(), 0, name->name);
HeapFree(GetProcessHeap(), 0, name->culture);
HeapFree(GetProcessHeap(), 0, name->procarch);
}
return hr;
}
/******************************************************************
* CreateAssemblyNameObject (FUSION.@)
*/
HRESULT WINAPI CreateAssemblyNameObject(IAssemblyName **ppAssemblyNameObj,
LPCWSTR szAssemblyName, DWORD dwFlags,
LPVOID pvReserved)
{
IAssemblyNameImpl *name;
HRESULT hr;
TRACE("(%p, %s, %08x, %p)\n", ppAssemblyNameObj,
debugstr_w(szAssemblyName), dwFlags, pvReserved);
if (!ppAssemblyNameObj)
return E_INVALIDARG;
if ((dwFlags & CANOF_PARSE_DISPLAY_NAME) &&
(!szAssemblyName || !*szAssemblyName))
return E_INVALIDARG;
name = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IAssemblyNameImpl));
if (!name)
return E_OUTOFMEMORY;
name->IAssemblyName_iface.lpVtbl = &AssemblyNameVtbl;
name->ref = 1;
hr = parse_display_name(name, szAssemblyName);
if (FAILED(hr))
{
HeapFree(GetProcessHeap(), 0, name);
return hr;
}
*ppAssemblyNameObj = &name->IAssemblyName_iface;
return S_OK;
}

930
dll/win32/fusion/assembly.c Normal file
View file

@ -0,0 +1,930 @@
/*
* assembly parser
*
* 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 "fusionpriv.h"
#include <wincrypt.h>
#include <dbghelp.h>
#include <corhdr.h>
#define TableFromToken(tk) (TypeFromToken(tk) >> 24)
#define TokenFromTable(idx) (idx << 24)
#define MAX_CLR_TABLES 64
#define MD_STRINGS_BIT 0x1
#define MD_GUIDS_BIT 0x2
#define MD_BLOBS_BIT 0x4
typedef struct tagCLRTABLE
{
INT rows;
DWORD offset;
} CLRTABLE;
struct tagASSEMBLY
{
LPWSTR path;
HANDLE hfile;
HANDLE hmap;
BYTE *data;
IMAGE_NT_HEADERS *nthdr;
IMAGE_COR20_HEADER *corhdr;
METADATAHDR *metadatahdr;
METADATATABLESHDR *tableshdr;
DWORD numtables;
DWORD *numrows;
CLRTABLE tables[MAX_CLR_TABLES];
DWORD stringsz;
DWORD guidsz;
DWORD blobsz;
BYTE *strings;
BYTE *blobs;
};
static DWORD rva_to_offset(IMAGE_NT_HEADERS *nthdrs, DWORD rva)
{
DWORD offset = rva, limit;
IMAGE_SECTION_HEADER *img;
WORD i;
img = IMAGE_FIRST_SECTION(nthdrs);
if (rva < img->PointerToRawData)
return rva;
for (i = 0; i < nthdrs->FileHeader.NumberOfSections; i++)
{
if (img[i].SizeOfRawData)
limit = img[i].SizeOfRawData;
else
limit = img[i].Misc.VirtualSize;
if (rva >= img[i].VirtualAddress &&
rva < (img[i].VirtualAddress + limit))
{
if (img[i].PointerToRawData != 0)
{
offset -= img[i].VirtualAddress;
offset += img[i].PointerToRawData;
}
return offset;
}
}
return 0;
}
static BYTE *GetData(BYTE *pData, ULONG *pLength)
{
if ((*pData & 0x80) == 0x00)
{
*pLength = (*pData & 0x7f);
return pData + 1;
}
if ((*pData & 0xC0) == 0x80)
{
*pLength = ((*pData & 0x3f) << 8 | *(pData + 1));
return pData + 2;
}
if ((*pData & 0xE0) == 0xC0)
{
*pLength = ((*pData & 0x1f) << 24 | *(pData + 1) << 16 |
*(pData + 2) << 8 | *(pData + 3));
return pData + 4;
}
*pLength = (ULONG)-1;
return 0;
}
static VOID *assembly_data_offset(ASSEMBLY *assembly, ULONG offset)
{
return &assembly->data[offset];
}
#define MAX_TABLES_WORD 0xFFFF
#define MAX_TABLES_1BIT_ENCODE 32767
#define MAX_TABLES_2BIT_ENCODE 16383
#define MAX_TABLES_3BIT_ENCODE 8191
#define MAX_TABLES_5BIT_ENCODE 2047
static inline ULONG get_table_size(const ASSEMBLY *assembly, DWORD index)
{
DWORD size;
INT tables;
switch (TokenFromTable(index))
{
case mdtModule:
{
size = sizeof(MODULETABLE) + (assembly->stringsz - sizeof(WORD)) +
2 * (assembly->guidsz - sizeof(WORD));
break;
}
case mdtTypeRef:
{
size = sizeof(TYPEREFTABLE) + 2 * (assembly->stringsz - sizeof(WORD));
/* ResolutionScope:ResolutionScope */
tables = max(assembly->tables[TableFromToken(mdtModule)].rows,
assembly->tables[TableFromToken(mdtModuleRef)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtAssemblyRef)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtTypeRef)].rows);
size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0;
break;
}
case mdtTypeDef:
{
size = sizeof(TYPEDEFTABLE) + 2 * (assembly->stringsz - sizeof(WORD));
/* Extends:TypeDefOrRef */
tables = max(assembly->tables[TableFromToken(mdtTypeDef)].rows,
assembly->tables[TableFromToken(mdtTypeRef)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtTypeSpec)].rows);
size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0;
size += (assembly->tables[TableFromToken(mdtFieldDef)].rows >
MAX_TABLES_WORD) ? sizeof(WORD) : 0;
size += (assembly->tables[TableFromToken(mdtMethodDef)].rows >
MAX_TABLES_WORD) ? sizeof(WORD) : 0;
break;
}
case mdtFieldDef:
{
size = sizeof(FIELDTABLE) + (assembly->stringsz - sizeof(WORD)) +
(assembly->blobsz - sizeof(WORD));
break;
}
case mdtMethodDef:
{
size = sizeof(METHODDEFTABLE) + (assembly->stringsz - sizeof(WORD)) +
(assembly->blobsz - sizeof(WORD));
size += (assembly->tables[TableFromToken(mdtParamDef)].rows >
MAX_TABLES_WORD) ? sizeof(WORD) : 0;
break;
}
case mdtParamDef:
{
size = sizeof(PARAMTABLE) + (assembly->stringsz - sizeof(WORD));
break;
}
case mdtInterfaceImpl:
{
size = sizeof(INTERFACEIMPLTABLE);
/* Interface:TypeDefOrRef */
tables = max(assembly->tables[TableFromToken(mdtTypeDef)].rows,
assembly->tables[TableFromToken(mdtTypeRef)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtTypeSpec)].rows);
size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0;
break;
}
case mdtMemberRef:
{
size = sizeof(MEMBERREFTABLE) + (assembly->stringsz - sizeof(WORD)) +
(assembly->blobsz - sizeof(WORD));
/* Class:MemberRefParent */
tables = max(assembly->tables[TableFromToken(mdtTypeRef)].rows,
assembly->tables[TableFromToken(mdtModuleRef)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtMethodDef)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtTypeSpec)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtTypeDef)].rows);
size += (tables > MAX_TABLES_3BIT_ENCODE) ? sizeof(WORD) : 0;
break;
}
case 0x0B000000: /* FIXME */
{
size = sizeof(CONSTANTTABLE) + (assembly->blobsz - sizeof(WORD));
/* Parent:HasConstant */
tables = max(assembly->tables[TableFromToken(mdtParamDef)].rows,
assembly->tables[TableFromToken(mdtFieldDef)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtProperty)].rows);
size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0;
break;
}
case mdtCustomAttribute:
{
size = sizeof(CUSTOMATTRIBUTETABLE) + (assembly->blobsz - sizeof(WORD));
/* Parent:HasCustomAttribute */
tables = max(assembly->tables[TableFromToken(mdtMethodDef)].rows,
assembly->tables[TableFromToken(mdtFieldDef)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtTypeRef)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtTypeDef)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtParamDef)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtInterfaceImpl)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtMemberRef)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtPermission)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtProperty)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtEvent)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtSignature)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtModuleRef)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtTypeSpec)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtAssembly)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtFile)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtExportedType)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtManifestResource)].rows);
size += (tables > MAX_TABLES_5BIT_ENCODE) ? sizeof(WORD) : 0;
/* Type:CustomAttributeType */
tables = max(assembly->tables[TableFromToken(mdtMethodDef)].rows,
assembly->tables[TableFromToken(mdtMemberRef)].rows);
size += (tables > MAX_TABLES_3BIT_ENCODE) ? sizeof(WORD) : 0;
break;
}
case 0x0D000000: /* FIXME */
{
size = sizeof(FIELDMARSHALTABLE) + (assembly->blobsz - sizeof(WORD));
/* Parent:HasFieldMarshal */
tables = max(assembly->tables[TableFromToken(mdtFieldDef)].rows,
assembly->tables[TableFromToken(mdtParamDef)].rows);
size += (tables > MAX_TABLES_1BIT_ENCODE) ? sizeof(WORD) : 0;
break;
}
case mdtPermission:
{
size = sizeof(DECLSECURITYTABLE) + (assembly->blobsz - sizeof(WORD));
/* Parent:HasDeclSecurity */
tables = max(assembly->tables[TableFromToken(mdtTypeDef)].rows,
assembly->tables[TableFromToken(mdtMethodDef)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtAssembly)].rows);
size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0;
break;
}
case 0x0F000000: /* FIXME */
{
size = sizeof(CLASSLAYOUTTABLE);
size += (assembly->tables[TableFromToken(mdtTypeDef)].rows >
MAX_TABLES_WORD) ? sizeof(WORD) : 0;
break;
}
case 0x10000000: /* FIXME */
{
size = sizeof(FIELDLAYOUTTABLE);
size += (assembly->tables[TableFromToken(mdtFieldDef)].rows >
MAX_TABLES_WORD) ? sizeof(WORD) : 0;
break;
}
case mdtSignature:
{
size = sizeof(STANDALONESIGTABLE) + (assembly->blobsz - sizeof(WORD));
break;
}
case 0x12000000: /* FIXME */
{
size = sizeof(EVENTMAPTABLE);
size += (assembly->tables[TableFromToken(mdtTypeDef)].rows >
MAX_TABLES_WORD) ? sizeof(WORD) : 0;
size += (assembly->tables[TableFromToken(mdtEvent)].rows >
MAX_TABLES_WORD) ? sizeof(WORD) : 0;
break;
}
case mdtEvent:
{
size = sizeof(EVENTTABLE) + (assembly->stringsz - sizeof(WORD));
/* EventType:TypeDefOrRef */
tables = max(assembly->tables[TableFromToken(mdtTypeDef)].rows,
assembly->tables[TableFromToken(mdtTypeRef)].rows);
tables = max(tables, assembly->tables[TableFromToken(mdtTypeSpec)].rows);
size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0;
break;
}
case 0x15000000:/* FIXME */
{
size = sizeof(PROPERTYMAPTABLE);
size += (assembly->tables[TableFromToken(mdtTypeDef)].rows >
MAX_TABLES_WORD) ? sizeof(WORD) : 0;
size += (assembly->tables[TableFromToken(mdtProperty)].rows >
MAX_TABLES_WORD) ? sizeof(WORD) : 0;
break;
}
case mdtProperty:
{
size = sizeof(PROPERTYTABLE) + (assembly->stringsz - sizeof(WORD)) +
(assembly->blobsz - sizeof(WORD));
break;
}
case 0x18000000: /* FIXME */
{
size = sizeof(METHODSEMANTICSTABLE);
/* Association:HasSemantics */
tables = max(assembly->tables[TableFromToken(mdtEvent)].rows,
assembly->tables[TableFromToken(mdtProperty)].rows);
size += (tables > MAX_TABLES_1BIT_ENCODE) ? sizeof(WORD) : 0;
size += (assembly->tables[TableFromToken(mdtMethodDef)].rows >
MAX_TABLES_WORD) ? sizeof(WORD) : 0;
break;
}
case 0x19000000: /* FIXME */
{
size = sizeof(METHODIMPLTABLE);
/* MethodBody:MethodDefOrRef, MethodDeclaration:MethodDefOrRef */
tables = max(assembly->tables[TableFromToken(mdtMethodDef)].rows,
assembly->tables[TableFromToken(mdtMemberRef)].rows);
size += (tables > MAX_TABLES_1BIT_ENCODE) ? 2 * sizeof(WORD) : 0;
size += (assembly->tables[TableFromToken(mdtTypeDef)].rows >
MAX_TABLES_WORD) ? sizeof(WORD) : 0;
break;
}
case mdtModuleRef:
{
size = sizeof(MODULEREFTABLE) + (assembly->stringsz - sizeof(WORD));
break;
}
case mdtTypeSpec:
{
size = sizeof(TYPESPECTABLE) + (assembly->blobsz - sizeof(WORD));
break;
}
case 0x1C000000: /* FIXME */
{
size = sizeof(IMPLMAPTABLE) + (assembly->stringsz - sizeof(WORD));
/* MemberForwarded:MemberForwarded */
tables = max(assembly->tables[TableFromToken(mdtFieldDef)].rows,
assembly->tables[TableFromToken(mdtMethodDef)].rows);
size += (tables > MAX_TABLES_1BIT_ENCODE) ? sizeof(WORD) : 0;
size += (assembly->tables[TableFromToken(mdtModuleRef)].rows >
MAX_TABLES_WORD) ? sizeof(WORD) : 0;
break;
}
case 0x1D000000: /* FIXME */
{
size = sizeof(FIELDRVATABLE);
size += (assembly->tables[TableFromToken(mdtFieldDef)].rows >
MAX_TABLES_WORD) ? sizeof(WORD) : 0;
break;
}
case mdtAssembly:
{
size = sizeof(ASSEMBLYTABLE) + 2 * (assembly->stringsz - sizeof(WORD)) +
(assembly->blobsz - sizeof(WORD));
break;
}
case 0x20000001: /* FIXME */
{
size = sizeof(ASSEMBLYPROCESSORTABLE);
break;
}
case 0x22000000: /* FIXME */
{
size = sizeof(ASSEMBLYOSTABLE);
break;
}
case mdtAssemblyRef:
{
size = sizeof(ASSEMBLYREFTABLE) + 2 * (assembly->stringsz - sizeof(WORD)) +
2 * (assembly->blobsz - sizeof(WORD));
break;
}
case 0x24000000: /* FIXME */
{
size = sizeof(ASSEMBLYREFPROCESSORTABLE);
size += (assembly->tables[TableFromToken(mdtAssemblyRef)].rows >
MAX_TABLES_WORD) ? sizeof(WORD) : 0;
break;
}
case 0x25000000: /* FIXME */
{
size = sizeof(ASSEMBLYREFOSTABLE);
size += (assembly->tables[TableFromToken(mdtAssemblyRef)].rows >
MAX_TABLES_WORD) ? sizeof(WORD) : 0;
break;
}
case mdtFile:
{
size = sizeof(FILETABLE) + (assembly->stringsz - sizeof(WORD)) +
(assembly->blobsz - sizeof(WORD));
break;
}
case mdtExportedType:
{
size = sizeof(EXPORTEDTYPETABLE) + 2 * (assembly->stringsz - sizeof(WORD));
/* Implementation:Implementation */
tables = max(assembly->tables[TableFromToken(mdtFile)].rows,
assembly->tables[TableFromToken(mdtMethodDef)].rows);
size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0;
break;
}
case mdtManifestResource:
{
size = sizeof(MANIFESTRESTABLE) + (assembly->stringsz - sizeof(WORD));
/* Implementation:Implementation */
tables = max(assembly->tables[TableFromToken(mdtFile)].rows,
assembly->tables[TableFromToken(mdtAssemblyRef)].rows);
size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0;
break;
}
case 0x29000000: /* FIXME */
{
size = sizeof(NESTEDCLASSTABLE);
size += (assembly->tables[TableFromToken(mdtTypeDef)].rows >
MAX_TABLES_WORD) ? 2 * sizeof(WORD) : 0;
break;
}
default:
return 0;
}
return size;
}
static HRESULT parse_clr_tables(ASSEMBLY *assembly, ULONG offset)
{
DWORD i, count;
ULONG currofs;
ULONGLONG mask;
currofs = offset;
assembly->tableshdr = assembly_data_offset(assembly, currofs);
if (!assembly->tableshdr)
return E_FAIL;
assembly->stringsz = (assembly->tableshdr->HeapOffsetSizes & MD_STRINGS_BIT) ?
sizeof(DWORD) : sizeof(WORD);
assembly->guidsz = (assembly->tableshdr->HeapOffsetSizes & MD_GUIDS_BIT) ?
sizeof(DWORD) : sizeof(WORD);
assembly->blobsz = (assembly->tableshdr->HeapOffsetSizes & MD_BLOBS_BIT) ?
sizeof(DWORD) : sizeof(WORD);
currofs += sizeof(METADATATABLESHDR);
assembly->numrows = assembly_data_offset(assembly, currofs);
if (!assembly->numrows)
return E_FAIL;
memset(assembly->tables, -1, MAX_CLR_TABLES * sizeof(CLRTABLE));
for (i = count = 0, mask = 1; i < MAX_CLR_TABLES; i++, mask <<= 1)
{
if (assembly->tableshdr->MaskValid.QuadPart & mask)
assembly->tables[i].rows = assembly->numrows[count++];
}
assembly->numtables = count;
currofs += assembly->numtables * sizeof(DWORD);
for (i = 0, mask = 1; i < MAX_CLR_TABLES; i++, mask <<= 1)
{
if (assembly->tableshdr->MaskValid.QuadPart & mask)
{
assembly->tables[i].offset = currofs;
currofs += get_table_size(assembly, i) * assembly->tables[i].rows;
}
}
return S_OK;
}
static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz)
{
METADATAHDR *metadatahdr;
BYTE *ptr, *dest;
DWORD size, ofs;
ULONG rva;
rva = assembly->corhdr->MetaData.VirtualAddress;
ptr = ImageRvaToVa(assembly->nthdr, assembly->data, rva, NULL);
if (!ptr)
return E_FAIL;
metadatahdr = (METADATAHDR *)ptr;
assembly->metadatahdr = HeapAlloc(GetProcessHeap(), 0, sizeof(METADATAHDR));
if (!assembly->metadatahdr)
return E_OUTOFMEMORY;
size = FIELD_OFFSET(METADATAHDR, Version);
memcpy(assembly->metadatahdr, metadatahdr, size);
assembly->metadatahdr->Version = (LPSTR)&metadatahdr->Version;
ofs = FIELD_OFFSET(METADATAHDR, Flags);
ptr += FIELD_OFFSET(METADATAHDR, Version) + metadatahdr->VersionLength + 1;
dest = (BYTE *)assembly->metadatahdr + ofs;
memcpy(dest, ptr, sizeof(METADATAHDR) - ofs);
*hdrsz = sizeof(METADATAHDR) - sizeof(LPSTR) + metadatahdr->VersionLength + 1;
return S_OK;
}
static HRESULT parse_clr_metadata(ASSEMBLY *assembly)
{
METADATASTREAMHDR *streamhdr;
ULONG rva, i, ofs;
LPSTR stream;
HRESULT hr;
DWORD hdrsz;
BYTE *ptr;
hr = parse_metadata_header(assembly, &hdrsz);
if (FAILED(hr))
return hr;
rva = assembly->corhdr->MetaData.VirtualAddress;
ptr = ImageRvaToVa(assembly->nthdr, assembly->data, rva + hdrsz, NULL);
if (!ptr)
return E_FAIL;
for (i = 0; i < assembly->metadatahdr->Streams; i++)
{
streamhdr = (METADATASTREAMHDR *)ptr;
ofs = rva_to_offset(assembly->nthdr, rva + streamhdr->Offset);
ptr += sizeof(METADATASTREAMHDR);
stream = (LPSTR)ptr;
if (!lstrcmpA(stream, "#~"))
{
hr = parse_clr_tables(assembly, ofs);
if (FAILED(hr))
return hr;
}
else if (!lstrcmpA(stream, "#Strings") || !lstrcmpA(stream, "Strings"))
assembly->strings = assembly_data_offset(assembly, ofs);
else if (!lstrcmpA(stream, "#Blob") || !lstrcmpA(stream, "Blob"))
assembly->blobs = assembly_data_offset(assembly, ofs);
ptr += ((lstrlenA(stream) + 1) + 3) & ~3; /* align on DWORD boundary */
}
return S_OK;
}
static HRESULT parse_pe_header(ASSEMBLY *assembly)
{
IMAGE_DATA_DIRECTORY *datadirs;
assembly->nthdr = ImageNtHeader(assembly->data);
if (!assembly->nthdr)
return E_FAIL;
if (assembly->nthdr->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
{
IMAGE_OPTIONAL_HEADER64 *opthdr =
(IMAGE_OPTIONAL_HEADER64 *)&assembly->nthdr->OptionalHeader;
datadirs = opthdr->DataDirectory;
}
else
{
IMAGE_OPTIONAL_HEADER32 *opthdr =
(IMAGE_OPTIONAL_HEADER32 *)&assembly->nthdr->OptionalHeader;
datadirs = opthdr->DataDirectory;
}
if (!datadirs)
return E_FAIL;
if (!datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress ||
!datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size)
{
return E_FAIL;
}
assembly->corhdr = ImageRvaToVa(assembly->nthdr, assembly->data,
datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress, NULL);
if (!assembly->corhdr)
return E_FAIL;
return S_OK;
}
HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
{
ASSEMBLY *assembly;
HRESULT hr;
*out = NULL;
assembly = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ASSEMBLY));
if (!assembly)
return E_OUTOFMEMORY;
assembly->path = strdupW(file);
if (!assembly->path)
{
hr = E_OUTOFMEMORY;
goto failed;
}
assembly->hfile = CreateFileW(file, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (assembly->hfile == INVALID_HANDLE_VALUE)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto failed;
}
assembly->hmap = CreateFileMappingW(assembly->hfile, NULL, PAGE_READONLY,
0, 0, NULL);
if (!assembly->hmap)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto failed;
}
assembly->data = MapViewOfFile(assembly->hmap, FILE_MAP_READ, 0, 0, 0);
if (!assembly->data)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto failed;
}
hr = parse_pe_header(assembly);
if (FAILED(hr)) goto failed;
hr = parse_clr_metadata(assembly);
if (FAILED(hr)) goto failed;
*out = assembly;
return S_OK;
failed:
assembly_release(assembly);
return hr;
}
HRESULT assembly_release(ASSEMBLY *assembly)
{
if (!assembly)
return S_OK;
HeapFree(GetProcessHeap(), 0, assembly->metadatahdr);
HeapFree(GetProcessHeap(), 0, assembly->path);
UnmapViewOfFile(assembly->data);
CloseHandle(assembly->hmap);
CloseHandle(assembly->hfile);
HeapFree(GetProcessHeap(), 0, assembly);
return S_OK;
}
static LPWSTR assembly_dup_str(const ASSEMBLY *assembly, DWORD index)
{
int len;
LPWSTR cpy;
LPCSTR str = (LPCSTR)&assembly->strings[index];
len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
if ((cpy = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))))
MultiByteToWideChar(CP_ACP, 0, str, -1, cpy, len);
return cpy;
}
HRESULT assembly_get_name(ASSEMBLY *assembly, LPWSTR *name)
{
BYTE *ptr;
LONG offset;
DWORD stridx;
offset = assembly->tables[TableFromToken(mdtAssembly)].offset;
if (offset == -1)
return E_FAIL;
ptr = assembly_data_offset(assembly, offset);
if (!ptr)
return E_FAIL;
ptr += FIELD_OFFSET(ASSEMBLYTABLE, PublicKey) + assembly->blobsz;
if (assembly->stringsz == sizeof(DWORD))
stridx = *(DWORD *)ptr;
else
stridx = *(WORD *)ptr;
*name = assembly_dup_str(assembly, stridx);
if (!*name)
return E_OUTOFMEMORY;
return S_OK;
}
HRESULT assembly_get_path(const ASSEMBLY *assembly, LPWSTR *path)
{
LPWSTR cpy = HeapAlloc(GetProcessHeap(), 0, (strlenW(assembly->path) + 1) * sizeof(WCHAR));
*path = cpy;
if (cpy)
strcpyW(cpy, assembly->path);
else
return E_OUTOFMEMORY;
return S_OK;
}
HRESULT assembly_get_version(ASSEMBLY *assembly, LPWSTR *version)
{
static const WCHAR format[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
ASSEMBLYTABLE *asmtbl;
LONG offset;
*version = NULL;
offset = assembly->tables[TableFromToken(mdtAssembly)].offset;
if (offset == -1)
return E_FAIL;
asmtbl = assembly_data_offset(assembly, offset);
if (!asmtbl)
return E_FAIL;
*version = HeapAlloc(GetProcessHeap(), 0, sizeof(format) + 4 * strlen("65535") * sizeof(WCHAR));
if (!*version)
return E_OUTOFMEMORY;
sprintfW(*version, format, asmtbl->MajorVersion, asmtbl->MinorVersion,
asmtbl->BuildNumber, asmtbl->RevisionNumber);
return S_OK;
}
PEKIND assembly_get_architecture(ASSEMBLY *assembly)
{
if ((assembly->corhdr->MajorRuntimeVersion == 2) && (assembly->corhdr->MinorRuntimeVersion == 0))
return peNone; /* .NET 1.x assembly */
if (assembly->nthdr->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
return peAMD64; /* AMD64/IA64 assembly */
if ((assembly->corhdr->Flags & COMIMAGE_FLAGS_ILONLY) && !(assembly->corhdr->Flags & COMIMAGE_FLAGS_32BITREQUIRED))
return peMSIL; /* MSIL assembly */
return peI386; /* x86 assembly */
}
static BYTE *assembly_get_blob(ASSEMBLY *assembly, DWORD index, ULONG *size)
{
return GetData(&assembly->blobs[index], size);
}
HRESULT assembly_get_pubkey_token(ASSEMBLY *assembly, LPWSTR *token)
{
ULONG i, size;
LONG offset;
BYTE *hashdata, *pubkey, *ptr;
HCRYPTPROV crypt;
HCRYPTHASH hash;
BYTE tokbytes[BYTES_PER_TOKEN];
HRESULT hr = E_FAIL;
LPWSTR tok;
DWORD idx;
*token = NULL;
offset = assembly->tables[TableFromToken(mdtAssembly)].offset;
if (offset == -1)
return E_FAIL;
ptr = assembly_data_offset(assembly, offset);
if (!ptr)
return E_FAIL;
ptr += FIELD_OFFSET(ASSEMBLYTABLE, PublicKey);
if (assembly->blobsz == sizeof(DWORD))
idx = *(DWORD *)ptr;
else
idx = *(WORD *)ptr;
pubkey = assembly_get_blob(assembly, idx, &size);
if (!CryptAcquireContextA(&crypt, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT))
return E_FAIL;
if (!CryptCreateHash(crypt, CALG_SHA1, 0, 0, &hash))
return E_FAIL;
if (!CryptHashData(hash, pubkey, size, 0))
return E_FAIL;
size = 0;
if (!CryptGetHashParam(hash, HP_HASHVAL, NULL, &size, 0))
return E_FAIL;
hashdata = HeapAlloc(GetProcessHeap(), 0, size);
if (!hashdata)
{
hr = E_OUTOFMEMORY;
goto done;
}
if (!CryptGetHashParam(hash, HP_HASHVAL, hashdata, &size, 0))
goto done;
for (i = size - 1; i >= size - 8; i--)
tokbytes[size - i - 1] = hashdata[i];
tok = HeapAlloc(GetProcessHeap(), 0, (TOKEN_LENGTH + 1) * sizeof(WCHAR));
if (!tok)
{
hr = E_OUTOFMEMORY;
goto done;
}
token_to_str(tokbytes, tok);
*token = tok;
hr = S_OK;
done:
HeapFree(GetProcessHeap(), 0, hashdata);
CryptDestroyHash(hash);
CryptReleaseContext(crypt, 0);
return hr;
}
HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version)
{
*version = assembly->metadatahdr->Version;
return S_OK;
}
HRESULT assembly_get_external_files(ASSEMBLY *assembly, LPWSTR **files, DWORD *count)
{
LONG offset;
INT i, num_rows;
WCHAR **ret;
BYTE *ptr;
DWORD idx;
*count = 0;
offset = assembly->tables[TableFromToken(mdtFile)].offset;
if (offset == -1)
return S_OK;
ptr = assembly_data_offset(assembly, offset);
if (!ptr)
return S_OK;
num_rows = assembly->tables[TableFromToken(mdtFile)].rows;
if (num_rows <= 0)
return S_OK;
ret = HeapAlloc(GetProcessHeap(), 0, num_rows * sizeof(WCHAR *));
if (!ret)
return E_OUTOFMEMORY;
for (i = 0; i < num_rows; i++)
{
ptr += sizeof(DWORD); /* skip Flags field */
if (assembly->stringsz == sizeof(DWORD))
idx = *(DWORD *)ptr;
else
idx = *(WORD *)ptr;
ret[i] = assembly_dup_str(assembly, idx);
if (!ret[i])
{
for (; i >= 0; i--) HeapFree(GetProcessHeap(), 0, ret[i]);
HeapFree(GetProcessHeap(), 0, ret);
return E_OUTOFMEMORY;
}
ptr += assembly->stringsz; /* skip Name field */
ptr += assembly->blobsz; /* skip Hash field */
}
*count = num_rows;
*files = ret;
return S_OK;
}

166
dll/win32/fusion/fusion.c Normal file
View file

@ -0,0 +1,166 @@
/*
* Implementation of the Fusion API
*
* 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 "fusionpriv.h"
/******************************************************************
* InitializeFusion (FUSION.@)
*/
HRESULT WINAPI InitializeFusion(void)
{
FIXME("\n");
return E_NOTIMPL;
}
/******************************************************************
* ClearDownloadCache (FUSION.@)
*/
HRESULT WINAPI ClearDownloadCache(void)
{
FIXME("stub!\n");
return E_NOTIMPL;
}
/******************************************************************
* CopyPDBs (FUSION.@)
*/
HRESULT WINAPI CopyPDBs(void *unknown)
{
FIXME("(%p) stub!\n", unknown);
return E_NOTIMPL;
}
/******************************************************************
* CreateInstallReferenceEnum (FUSION.@)
*/
HRESULT WINAPI CreateInstallReferenceEnum(IInstallReferenceEnum **ppRefEnum,
IAssemblyName *pName, DWORD dwFlags,
LPVOID pvReserved)
{
FIXME("(%p, %p, %08x, %p) stub!\n", ppRefEnum, pName, dwFlags, pvReserved);
return E_NOTIMPL;
}
/******************************************************************
* CreateApplicationContext (FUSION.@)
*/
HRESULT WINAPI CreateApplicationContext(IAssemblyName *name, void *ctx)
{
FIXME("%p, %p\n", name, ctx);
return E_NOTIMPL;
}
static HRESULT (WINAPI *pGetCORVersion)(LPWSTR pbuffer, DWORD cchBuffer,
DWORD *dwLength);
static HRESULT get_corversion(LPWSTR version, DWORD size)
{
HMODULE hmscoree;
HRESULT hr;
DWORD len;
hmscoree = LoadLibraryA("mscoree.dll");
if (!hmscoree)
return E_FAIL;
pGetCORVersion = (void *)GetProcAddress(hmscoree, "GetCORVersion");
if (!pGetCORVersion)
hr = E_FAIL;
else
hr = pGetCORVersion(version, size, &len);
FreeLibrary(hmscoree);
return hr;
}
/******************************************************************
* GetCachePath (FUSION.@)
*/
HRESULT WINAPI GetCachePath(ASM_CACHE_FLAGS dwCacheFlags, LPWSTR pwzCachePath,
PDWORD pcchPath)
{
static const WCHAR assembly[] = {'\\','a','s','s','e','m','b','l','y',0};
static const WCHAR gac[] = {'\\','G','A','C',0};
static const WCHAR nativeimg[] = {'N','a','t','i','v','e','I','m','a','g','e','s','_',0};
static const WCHAR dotnet[] = {'\\','M','i','c','r','o','s','o','f','t','.','N','E','T',0};
#ifdef _WIN64
static const WCHAR zapfmt[] = {'%','s','\\','%','s','\\','%','s','%','s','_','6','4',0};
#else
static const WCHAR zapfmt[] = {'%','s','\\','%','s','\\','%','s','%','s','_','3','2',0};
#endif
WCHAR path[MAX_PATH], windir[MAX_PATH], version[MAX_PATH];
DWORD len;
HRESULT hr = S_OK;
TRACE("(%08x, %p, %p)\n", dwCacheFlags, pwzCachePath, pcchPath);
if (!pcchPath)
return E_INVALIDARG;
len = GetWindowsDirectoryW(windir, MAX_PATH);
strcpyW(path, windir);
switch (dwCacheFlags)
{
case ASM_CACHE_ZAP:
{
hr = get_corversion(version, MAX_PATH);
if (FAILED(hr))
return hr;
len = sprintfW(path, zapfmt, windir, assembly + 1, nativeimg, version);
break;
}
case ASM_CACHE_GAC:
{
strcpyW(path + len, assembly);
len += sizeof(assembly)/sizeof(WCHAR) - 1;
strcpyW(path + len, gac);
len += sizeof(gac)/sizeof(WCHAR) - 1;
break;
}
case ASM_CACHE_DOWNLOAD:
{
FIXME("Download cache not implemented\n");
return E_FAIL;
}
case ASM_CACHE_ROOT:
strcpyW(path + len, assembly);
len += sizeof(assembly)/sizeof(WCHAR) - 1;
break;
case ASM_CACHE_ROOT_EX:
strcpyW(path + len, dotnet);
len += sizeof(dotnet)/sizeof(WCHAR) - 1;
strcpyW(path + len, assembly);
len += sizeof(assembly)/sizeof(WCHAR) - 1;
break;
default:
return E_INVALIDARG;
}
len++;
if (*pcchPath <= len || !pwzCachePath)
hr = E_NOT_SUFFICIENT_BUFFER;
else if (pwzCachePath)
strcpyW(pwzCachePath, path);
*pcchPath = len;
return hr;
}

View file

@ -0,0 +1,17 @@
@ stdcall CopyPDBs(ptr)
@ stdcall ClearDownloadCache()
@ stdcall CreateApplicationContext(ptr ptr)
@ stdcall CreateAssemblyCache(ptr long)
@ stdcall CreateAssemblyEnum(ptr ptr ptr long ptr)
@ stdcall CreateAssemblyNameObject(ptr wstr long ptr)
@ stub CreateHistoryReader
@ stdcall CreateInstallReferenceEnum(ptr ptr long ptr)
@ stdcall GetCachePath(long wstr ptr)
@ stub GetHistoryFileDirectory
@ stdcall InitializeFusion()
@ stub InstallCustomAssembly
@ stub InstallCustomModule
@ stub LookupHistoryAssembly
@ stub NukeDownloadedCache
@ stub PreBindAssembly
@ stub PreBindAssemblyEx

View file

@ -0,0 +1,13 @@
set(fusion_folder "${CMAKE_CURRENT_SOURCE_DIR}/..")
spec2def(fusion.dll fusion.spec)
add_library(fusion_1_1 SHARED
${fusion_folder}/version.rc
${CMAKE_CURRENT_BINARY_DIR}/fusion.def)
set_module_type(fusion_1_1 win32dll)
target_link_libraries(fusion_1_1 fusion_common uuid wine)
set_target_properties(fusion_1_1 PROPERTIES OUTPUT_NAME "fusion" PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
add_importlibs(fusion_1_1 advapi32 dbghelp shlwapi user32 msvcrt kernel32 ntdll)
add_cd_file(TARGET fusion_1_1 DESTINATION reactos/Microsoft.NET/Framework/v1.1.4322 FOR all)

View file

@ -0,0 +1,17 @@
@ stdcall CopyPDBs(ptr)
@ stdcall ClearDownloadCache()
@ stdcall CreateApplicationContext(ptr ptr)
@ stdcall CreateAssemblyCache(ptr long)
@ stdcall CreateAssemblyEnum(ptr ptr ptr long ptr)
@ stdcall CreateAssemblyNameObject(ptr wstr long ptr)
@ stub CreateHistoryReader
@ stdcall CreateInstallReferenceEnum(ptr ptr long ptr)
@ stdcall GetCachePath(long wstr ptr)
@ stub GetHistoryFileDirectory
@ stdcall InitializeFusion()
@ stub InstallCustomAssembly
@ stub InstallCustomModule
@ stub LookupHistoryAssembly
@ stub NukeDownloadedCache
@ stub PreBindAssembly
@ stub PreBindAssemblyEx

View file

@ -0,0 +1,13 @@
set(fusion_folder "${CMAKE_CURRENT_SOURCE_DIR}/..")
spec2def(fusion.dll fusion.spec)
add_library(fusion_2_0 SHARED
${fusion_folder}/version.rc
${CMAKE_CURRENT_BINARY_DIR}/fusion.def)
set_module_type(fusion_2_0 win32dll)
target_link_libraries(fusion_2_0 fusion_common uuid wine)
set_target_properties(fusion_2_0 PROPERTIES OUTPUT_NAME "fusion" PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
add_importlibs(fusion_2_0 advapi32 dbghelp shlwapi user32 msvcrt kernel32 ntdll)
add_cd_file(TARGET fusion_2_0 DESTINATION reactos/Microsoft.NET/Framework/v2.0.50727 FOR all)

View file

@ -0,0 +1,17 @@
@ stdcall CopyPDBs(ptr)
@ stdcall ClearDownloadCache()
@ stdcall CreateApplicationContext(ptr ptr)
@ stdcall CreateAssemblyCache(ptr long)
@ stdcall CreateAssemblyEnum(ptr ptr ptr long ptr)
@ stdcall CreateAssemblyNameObject(ptr wstr long ptr)
@ stub CreateHistoryReader
@ stdcall CreateInstallReferenceEnum(ptr ptr long ptr)
@ stdcall GetCachePath(long wstr ptr)
@ stub GetHistoryFileDirectory
@ stdcall InitializeFusion()
@ stub InstallCustomAssembly
@ stub InstallCustomModule
@ stub LookupHistoryAssembly
@ stub NukeDownloadedCache
@ stub PreBindAssembly
@ stub PreBindAssemblyEx

View file

@ -0,0 +1,493 @@
/*
* fusion private definitions
*
* 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
*/
#ifndef __WINE_FUSION_PRIVATE__
#define __WINE_FUSION_PRIVATE__
#include <stdarg.h>
#define WIN32_NO_STATUS
#define _INC_WINDOWS
#define COM_NO_WINDOWS_H
#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include <windef.h>
#include <winbase.h>
#include <winver.h>
#include <objbase.h>
#include <fusion.h>
#include <corerror.h>
#include <wine/unicode.h>
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(fusion);
#include <pshpack1.h>
typedef struct
{
ULONG Signature;
USHORT MajorVersion;
USHORT MinorVersion;
ULONG Reserved;
ULONG VersionLength;
LPSTR Version;
BYTE Flags;
WORD Streams;
} METADATAHDR;
typedef struct
{
DWORD Offset;
DWORD Size;
} METADATASTREAMHDR;
typedef struct
{
DWORD Reserved1;
BYTE MajorVersion;
BYTE MinorVersion;
BYTE HeapOffsetSizes;
BYTE Reserved2;
LARGE_INTEGER MaskValid;
LARGE_INTEGER MaskSorted;
} METADATATABLESHDR;
typedef struct
{
WORD Generation;
WORD Name;
WORD Mvid;
WORD EncId;
WORD EncBaseId;
} MODULETABLE;
typedef struct
{
DWORD Flags;
WORD Name;
WORD Namespace;
WORD Extends;
WORD FieldList;
WORD MethodList;
} TYPEDEFTABLE;
typedef struct
{
WORD ResolutionScope;
WORD Name;
WORD Namespace;
} TYPEREFTABLE;
typedef struct
{
WORD Flags;
WORD Name;
WORD Signature;
} FIELDTABLE;
typedef struct
{
DWORD HashAlgId;
WORD MajorVersion;
WORD MinorVersion;
WORD BuildNumber;
WORD RevisionNumber;
DWORD Flags;
WORD PublicKey;
WORD Name;
WORD Culture;
} ASSEMBLYTABLE;
typedef struct
{
DWORD Offset;
DWORD Flags;
WORD Name;
WORD Implementation;
} MANIFESTRESTABLE;
typedef struct
{
DWORD RVA;
WORD ImplFlags;
WORD Flags;
WORD Name;
WORD Signature;
WORD ParamList;
} METHODDEFTABLE;
typedef struct
{
WORD Flags;
WORD Sequence;
WORD Name;
} PARAMTABLE;
typedef struct
{
WORD Class;
WORD Interface;
} INTERFACEIMPLTABLE;
typedef struct
{
WORD Class;
WORD Name;
WORD Signature;
} MEMBERREFTABLE;
typedef struct
{
BYTE Type;
BYTE Reserved;
WORD Parent;
WORD Value;
} CONSTANTTABLE;
typedef struct
{
WORD Parent;
WORD Type;
WORD Value;
} CUSTOMATTRIBUTETABLE;
typedef struct
{
WORD Parent;
WORD NativeType;
} FIELDMARSHALTABLE;
typedef struct
{
WORD Action;
WORD Parent;
WORD PermissionSet;
} DECLSECURITYTABLE;
typedef struct
{
WORD PackingSize;
DWORD ClassSize;
WORD Parent;
} CLASSLAYOUTTABLE;
typedef struct
{
DWORD Offset;
WORD Field;
} FIELDLAYOUTTABLE;
typedef struct
{
WORD Signature;
} STANDALONESIGTABLE;
typedef struct
{
WORD Parent;
WORD EventList;
} EVENTMAPTABLE;
typedef struct
{
WORD EventFlags;
WORD Name;
WORD EventType;
} EVENTTABLE;
typedef struct
{
WORD Parent;
WORD PropertyList;
} PROPERTYMAPTABLE;
typedef struct
{
WORD Flags;
WORD Name;
WORD Type;
} PROPERTYTABLE;
typedef struct
{
WORD Semantics;
WORD Method;
WORD Association;
} METHODSEMANTICSTABLE;
typedef struct
{
WORD Class;
WORD MethodBody;
WORD MethodDeclaration;
} METHODIMPLTABLE;
typedef struct
{
WORD Name;
} MODULEREFTABLE;
typedef struct
{
WORD Signature;
} TYPESPECTABLE;
typedef struct
{
WORD MappingFlags;
WORD MemberForwarded;
WORD ImportName;
WORD ImportScope;
} IMPLMAPTABLE;
typedef struct
{
DWORD RVA;
WORD Field;
} FIELDRVATABLE;
typedef struct
{
DWORD Processor;
} ASSEMBLYPROCESSORTABLE;
typedef struct
{
DWORD OSPlatformID;
DWORD OSMajorVersion;
DWORD OSMinorVersion;
} ASSEMBLYOSTABLE;
typedef struct
{
WORD MajorVersion;
WORD MinorVersion;
WORD BuildNumber;
WORD RevisionNumber;
DWORD Flags;
WORD PublickKeyOrToken;
WORD Name;
WORD Culture;
WORD HashValue;
} ASSEMBLYREFTABLE;
typedef struct
{
DWORD Processor;
WORD AssemblyRef;
} ASSEMBLYREFPROCESSORTABLE;
typedef struct
{
DWORD OSPlatformId;
DWORD OSMajorVersion;
DWORD OSMinorVersion;
WORD AssemblyRef;
} ASSEMBLYREFOSTABLE;
typedef struct
{
DWORD Flags;
WORD Name;
WORD HashValue;
} FILETABLE;
typedef struct
{
DWORD Flags;
DWORD TypeDefId;
WORD TypeName;
WORD TypeNameSpace;
WORD Implementation;
} EXPORTEDTYPETABLE;
typedef struct
{
WORD NestedClass;
WORD EnclosingClass;
} NESTEDCLASSTABLE;
typedef struct
{
WORD Number;
WORD Flags;
} GENERICPARAMTABLE;
typedef struct
{
WORD MethodDef;
WORD Instantiation;
} METHODSPECTABLE;
typedef struct
{
WORD Owner;
WORD Constraint;
} GENERICPARAMCONSTRAINTTABLE;
typedef struct
{
DWORD ImportLookupTable;
DWORD DateTimeStamp;
DWORD ForwarderChain;
DWORD Name;
DWORD ImportAddressTable;
BYTE pad[20];
} IMPORTTABLE;
typedef struct
{
DWORD HintNameTableRVA;
BYTE pad[8];
} IMPORTLOOKUPTABLE;
typedef struct
{
WORD Hint;
BYTE Name[12];
BYTE Module[12];
DWORD Reserved;
WORD EntryPoint;
DWORD RVA;
} HINTNAMETABLE;
typedef struct
{
DWORD PageRVA;
DWORD Size;
DWORD Relocation;
} RELOCATION;
typedef struct
{
WORD wLength;
WORD wValueLength;
WORD wType;
WCHAR szKey[17];
VS_FIXEDFILEINFO Value;
} VS_VERSIONINFO;
typedef struct
{
WORD wLength;
WORD wValueLength;
WORD wType;
WCHAR szKey[13];
} VARFILEINFO;
typedef struct
{
WORD wLength;
WORD wValueLength;
WORD wType;
WCHAR szKey[13];
DWORD Value;
} VAR;
typedef struct
{
WORD wLength;
WORD wValueLength;
WORD wType;
WCHAR szKey[15];
} STRINGFILEINFO;
typedef struct
{
WORD wLength;
WORD wValueLength;
WORD wType;
WCHAR szKey[9];
} STRINGTABLE;
typedef struct
{
WORD wLength;
WORD wValueLength;
WORD wType;
} STRINGHDR;
typedef struct
{
DWORD Size;
DWORD Signature;
DWORD HeaderVersion;
DWORD SkipData;
BYTE Data[168];
} RESOURCE;
#include <poppack.h>
struct tagASSEMBLY;
typedef struct tagASSEMBLY ASSEMBLY;
HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) DECLSPEC_HIDDEN;
HRESULT assembly_release(ASSEMBLY *assembly) DECLSPEC_HIDDEN;
HRESULT assembly_get_name(ASSEMBLY *assembly, LPWSTR *name) DECLSPEC_HIDDEN;
HRESULT assembly_get_path(const ASSEMBLY *assembly, LPWSTR *path) DECLSPEC_HIDDEN;
HRESULT assembly_get_version(ASSEMBLY *assembly, LPWSTR *version) DECLSPEC_HIDDEN;
PEKIND assembly_get_architecture(ASSEMBLY *assembly) DECLSPEC_HIDDEN;
HRESULT assembly_get_pubkey_token(ASSEMBLY *assembly, LPWSTR *token) DECLSPEC_HIDDEN;
HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version) DECLSPEC_HIDDEN;
HRESULT assembly_get_external_files(ASSEMBLY *assembly, LPWSTR **files, DWORD *count) DECLSPEC_HIDDEN;
extern HRESULT IAssemblyName_SetPath(IAssemblyName *iface, LPCWSTR path) DECLSPEC_HIDDEN;
extern HRESULT IAssemblyName_GetPath(IAssemblyName *iface, LPWSTR buf, ULONG *len) DECLSPEC_HIDDEN;
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;
}
#define BYTES_PER_TOKEN 8
#define CHARS_PER_BYTE 2
#define TOKEN_LENGTH (BYTES_PER_TOKEN * CHARS_PER_BYTE + 1)
static inline void token_to_str(BYTE *bytes, LPWSTR str)
{
DWORD i;
static const WCHAR hexval[] = {
'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
};
for(i = 0; i < BYTES_PER_TOKEN; i++)
{
str[i * 2] = hexval[((bytes[i] >> 4) & 0xF)];
str[i * 2 + 1] = hexval[(bytes[i]) & 0x0F];
}
str[i * 2] = 0;
}
#endif /* __WINE_FUSION_PRIVATE__ */

View file

@ -0,0 +1,26 @@
/*
* Copyright 2010 Louis Lenders
*
* 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
*/
#define WINE_FILEDESCRIPTION_STR "Wine assembly manager"
#define WINE_FILENAME_STR "fusion.dll"
#define WINE_FILEVERSION 2,0,50727,4016
#define WINE_FILEVERSION_STR "2.0.50727.4016"
#define WINE_PRODUCTVERSION 2,0,50727,4016
#define WINE_PRODUCTVERSION_STR "2.0.50727.4016"
#include "wine/wine_common_ver.rc"