mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 06:35:42 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
30
dll/win32/fusion/CMakeLists.txt
Normal file
30
dll/win32/fusion/CMakeLists.txt
Normal 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
649
dll/win32/fusion/asmcache.c
Normal 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
485
dll/win32/fusion/asmenum.c
Normal 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
749
dll/win32/fusion/asmname.c
Normal 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
930
dll/win32/fusion/assembly.c
Normal 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
166
dll/win32/fusion/fusion.c
Normal 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;
|
||||
}
|
17
dll/win32/fusion/fusion.spec
Normal file
17
dll/win32/fusion/fusion.spec
Normal 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
|
13
dll/win32/fusion/fusion_1_1/CMakeLists.txt
Normal file
13
dll/win32/fusion/fusion_1_1/CMakeLists.txt
Normal 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)
|
17
dll/win32/fusion/fusion_1_1/fusion.spec
Normal file
17
dll/win32/fusion/fusion_1_1/fusion.spec
Normal 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
|
13
dll/win32/fusion/fusion_2_0/CMakeLists.txt
Normal file
13
dll/win32/fusion/fusion_2_0/CMakeLists.txt
Normal 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)
|
17
dll/win32/fusion/fusion_2_0/fusion.spec
Normal file
17
dll/win32/fusion/fusion_2_0/fusion.spec
Normal 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
|
493
dll/win32/fusion/fusionpriv.h
Normal file
493
dll/win32/fusion/fusionpriv.h
Normal 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__ */
|
26
dll/win32/fusion/version.rc
Normal file
26
dll/win32/fusion/version.rc
Normal 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"
|
Loading…
Add table
Add a link
Reference in a new issue