2008-09-10 08:47:30 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2018-03-09 12:07:30 +00:00
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#define COBJMACROS
|
2019-10-26 21:56:11 +00:00
|
|
|
#ifdef __REACTOS__
|
|
|
|
#define WIN32_NO_STATUS
|
|
|
|
#endif
|
2018-03-09 12:07:30 +00:00
|
|
|
|
|
|
|
#include "windef.h"
|
|
|
|
#include "winbase.h"
|
|
|
|
#include "winuser.h"
|
|
|
|
#include "winver.h"
|
|
|
|
#include "wincrypt.h"
|
|
|
|
#include "winreg.h"
|
|
|
|
#include "shlwapi.h"
|
|
|
|
#include "dbghelp.h"
|
|
|
|
#include "ole2.h"
|
|
|
|
#include "fusion.h"
|
|
|
|
#include "corerror.h"
|
|
|
|
|
2008-09-10 08:47:30 +00:00
|
|
|
#include "fusionpriv.h"
|
2018-03-09 12:07:30 +00:00
|
|
|
#include "wine/debug.h"
|
|
|
|
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(fusion);
|
2008-09-10 08:47:30 +00:00
|
|
|
|
2015-03-21 12:21:40 +00:00
|
|
|
typedef struct {
|
|
|
|
IAssemblyCache IAssemblyCache_iface;
|
|
|
|
|
|
|
|
LONG ref;
|
|
|
|
HANDLE lock;
|
|
|
|
} IAssemblyCacheImpl;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
IAssemblyCacheItem IAssemblyCacheItem_iface;
|
|
|
|
|
|
|
|
LONG ref;
|
|
|
|
} IAssemblyCacheItemImpl;
|
|
|
|
|
2012-05-19 09:41:07 +00:00
|
|
|
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};
|
|
|
|
|
2009-05-20 14:43:24 +00:00
|
|
|
static BOOL create_full_path(LPCWSTR path)
|
2008-09-10 08:47:30 +00:00
|
|
|
{
|
2009-05-20 14:43:24 +00:00
|
|
|
LPWSTR new_path;
|
2008-09-10 08:47:30 +00:00
|
|
|
BOOL ret = TRUE;
|
|
|
|
int len;
|
|
|
|
|
2019-10-26 21:56:11 +00:00
|
|
|
if (!(new_path = heap_alloc((lstrlenW(path) + 1) * sizeof(WCHAR)))) return FALSE;
|
2008-09-10 08:47:30 +00:00
|
|
|
|
2019-10-26 21:56:11 +00:00
|
|
|
lstrcpyW(new_path, path);
|
2008-09-10 08:47:30 +00:00
|
|
|
|
2019-10-26 21:56:11 +00:00
|
|
|
while ((len = lstrlenW(new_path)) && new_path[len - 1] == '\\')
|
2008-09-10 08:47:30 +00:00
|
|
|
new_path[len - 1] = 0;
|
|
|
|
|
2009-05-20 14:43:24 +00:00
|
|
|
while (!CreateDirectoryW(new_path, NULL))
|
2008-09-10 08:47:30 +00:00
|
|
|
{
|
2009-05-20 14:43:24 +00:00
|
|
|
LPWSTR slash;
|
2008-09-10 08:47:30 +00:00
|
|
|
DWORD last_error = GetLastError();
|
|
|
|
|
|
|
|
if(last_error == ERROR_ALREADY_EXISTS)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if(last_error != ERROR_PATH_NOT_FOUND)
|
|
|
|
{
|
|
|
|
ret = FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-10-26 21:56:11 +00:00
|
|
|
if(!(slash = wcsrchr(new_path, '\\')))
|
2008-09-10 08:47:30 +00:00
|
|
|
{
|
|
|
|
ret = FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = slash - new_path;
|
|
|
|
new_path[len] = 0;
|
|
|
|
if(!create_full_path(new_path))
|
|
|
|
{
|
|
|
|
ret = FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
new_path[len] = '\\';
|
|
|
|
}
|
|
|
|
|
2018-03-09 12:07:30 +00:00
|
|
|
heap_free(new_path);
|
2008-09-10 08:47:30 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-05-04 20:21:39 +00:00
|
|
|
static BOOL get_assembly_directory(LPWSTR dir, DWORD size, const char *version, PEKIND architecture)
|
2009-05-20 14:43:24 +00:00
|
|
|
{
|
2013-05-04 20:21:39 +00:00
|
|
|
static const WCHAR dotnet[] = {'\\','M','i','c','r','o','s','o','f','t','.','N','E','T','\\',0};
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
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};
|
2013-05-04 20:21:39 +00:00
|
|
|
DWORD len = GetWindowsDirectoryW(dir, size);
|
2009-05-20 14:43:24 +00:00
|
|
|
|
2013-05-04 20:21:39 +00:00
|
|
|
if (!strcmp(version, "v4.0.30319"))
|
|
|
|
{
|
2019-10-26 21:56:11 +00:00
|
|
|
lstrcpyW(dir + len, dotnet);
|
2018-10-01 11:49:44 +00:00
|
|
|
len += ARRAY_SIZE(dotnet) - 1;
|
2019-10-26 21:56:11 +00:00
|
|
|
lstrcpyW(dir + len, gac + 1);
|
2018-10-01 11:49:44 +00:00
|
|
|
len += ARRAY_SIZE(gac) - 2;
|
2013-05-04 20:21:39 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-10-26 21:56:11 +00:00
|
|
|
lstrcpyW(dir + len, gac);
|
2018-10-01 11:49:44 +00:00
|
|
|
len += ARRAY_SIZE(gac) - 1;
|
2013-05-04 20:21:39 +00:00
|
|
|
}
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
switch (architecture)
|
|
|
|
{
|
2013-05-04 20:21:39 +00:00
|
|
|
case peNone:
|
|
|
|
break;
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
case peMSIL:
|
2019-10-26 21:56:11 +00:00
|
|
|
lstrcpyW(dir + len, msil);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case peI386:
|
2019-10-26 21:56:11 +00:00
|
|
|
lstrcpyW(dir + len, x86);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case peAMD64:
|
2019-10-26 21:56:11 +00:00
|
|
|
lstrcpyW(dir + len, amd64);
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
break;
|
|
|
|
|
2013-05-04 20:21:39 +00:00
|
|
|
default:
|
|
|
|
WARN("unhandled architecture %u\n", architecture);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2009-05-20 14:43:24 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-09-10 08:47:30 +00:00
|
|
|
/* IAssemblyCache */
|
|
|
|
|
2010-12-27 09:50:02 +00:00
|
|
|
static inline IAssemblyCacheImpl *impl_from_IAssemblyCache(IAssemblyCache *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, IAssemblyCacheImpl, IAssemblyCache_iface);
|
|
|
|
}
|
|
|
|
|
2008-09-10 08:47:30 +00:00
|
|
|
static HRESULT WINAPI IAssemblyCacheImpl_QueryInterface(IAssemblyCache *iface,
|
|
|
|
REFIID riid, LPVOID *ppobj)
|
|
|
|
{
|
2010-12-27 09:50:02 +00:00
|
|
|
IAssemblyCacheImpl *This = impl_from_IAssemblyCache(iface);
|
2008-09-10 08:47:30 +00:00
|
|
|
|
|
|
|
TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
|
|
|
|
|
|
|
|
*ppobj = NULL;
|
|
|
|
|
|
|
|
if (IsEqualIID(riid, &IID_IUnknown) ||
|
|
|
|
IsEqualIID(riid, &IID_IAssemblyCache))
|
|
|
|
{
|
2013-05-04 20:21:39 +00:00
|
|
|
IAssemblyCache_AddRef(iface);
|
2015-07-19 13:16:45 +00:00
|
|
|
*ppobj = &This->IAssemblyCache_iface;
|
2008-09-10 08:47:30 +00:00
|
|
|
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)
|
|
|
|
{
|
2010-12-27 09:50:02 +00:00
|
|
|
IAssemblyCacheImpl *This = impl_from_IAssemblyCache(iface);
|
2008-09-10 08:47:30 +00:00
|
|
|
ULONG refCount = InterlockedIncrement(&This->ref);
|
|
|
|
|
|
|
|
TRACE("(%p)->(ref before = %u)\n", This, refCount - 1);
|
|
|
|
|
|
|
|
return refCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI IAssemblyCacheImpl_Release(IAssemblyCache *iface)
|
|
|
|
{
|
2012-05-19 09:41:07 +00:00
|
|
|
IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface);
|
|
|
|
ULONG refCount = InterlockedDecrement( &cache->ref );
|
2008-09-10 08:47:30 +00:00
|
|
|
|
2012-05-19 09:41:07 +00:00
|
|
|
TRACE("(%p)->(ref before = %u)\n", cache, refCount + 1);
|
2008-09-10 08:47:30 +00:00
|
|
|
|
|
|
|
if (!refCount)
|
2012-05-19 09:41:07 +00:00
|
|
|
{
|
|
|
|
CloseHandle( cache->lock );
|
2018-03-09 12:07:30 +00:00
|
|
|
heap_free( cache );
|
2012-05-19 09:41:07 +00:00
|
|
|
}
|
2008-09-10 08:47:30 +00:00
|
|
|
return refCount;
|
|
|
|
}
|
|
|
|
|
2012-05-19 09:41:07 +00:00
|
|
|
static void cache_lock( IAssemblyCacheImpl *cache )
|
|
|
|
{
|
|
|
|
WaitForSingleObject( cache->lock, INFINITE );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cache_unlock( IAssemblyCacheImpl *cache )
|
|
|
|
{
|
|
|
|
ReleaseMutex( cache->lock );
|
|
|
|
}
|
|
|
|
|
2008-09-10 08:47:30 +00:00
|
|
|
static HRESULT WINAPI IAssemblyCacheImpl_UninstallAssembly(IAssemblyCache *iface,
|
|
|
|
DWORD dwFlags,
|
|
|
|
LPCWSTR pszAssemblyName,
|
|
|
|
LPCFUSION_INSTALL_REFERENCE pRefData,
|
|
|
|
ULONG *pulDisposition)
|
|
|
|
{
|
2012-05-19 09:41:07 +00:00
|
|
|
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,
|
2008-09-10 08:47:30 +00:00
|
|
|
debugstr_w(pszAssemblyName), pRefData, pulDisposition);
|
|
|
|
|
2012-05-19 09:41:07 +00:00
|
|
|
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;
|
|
|
|
|
2018-03-09 12:07:30 +00:00
|
|
|
if (!(path = heap_alloc( len * sizeof(WCHAR) )))
|
2012-05-19 09:41:07 +00:00
|
|
|
{
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
hr = IAssemblyName_GetPath( next, path, &len );
|
|
|
|
if (FAILED( hr ))
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
if (DeleteFileW( path ))
|
|
|
|
{
|
2019-10-26 21:56:11 +00:00
|
|
|
if ((p = wcsrchr( path, '\\' )))
|
2012-05-19 09:41:07 +00:00
|
|
|
{
|
|
|
|
*p = 0;
|
|
|
|
RemoveDirectoryW( path );
|
2019-10-26 21:56:11 +00:00
|
|
|
if ((p = wcsrchr( path, '\\' )))
|
2012-05-19 09:41:07 +00:00
|
|
|
{
|
|
|
|
*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 );
|
2018-03-09 12:07:30 +00:00
|
|
|
heap_free( path );
|
2012-05-19 09:41:07 +00:00
|
|
|
cache_unlock( cache );
|
|
|
|
return hr;
|
2008-09-10 08:47:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IAssemblyCacheImpl_QueryAssemblyInfo(IAssemblyCache *iface,
|
|
|
|
DWORD dwFlags,
|
|
|
|
LPCWSTR pszAssemblyName,
|
|
|
|
ASSEMBLY_INFO *pAsmInfo)
|
|
|
|
{
|
2012-05-19 09:41:07 +00:00
|
|
|
IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface);
|
2009-05-20 14:43:24 +00:00
|
|
|
IAssemblyName *asmname, *next = NULL;
|
|
|
|
IAssemblyEnum *asmenum = NULL;
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
TRACE("(%p, %d, %s, %p)\n", iface, dwFlags,
|
2008-09-10 08:47:30 +00:00
|
|
|
debugstr_w(pszAssemblyName), pAsmInfo);
|
|
|
|
|
2009-05-20 14:43:24 +00:00
|
|
|
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;
|
|
|
|
|
2012-05-19 09:41:07 +00:00
|
|
|
cache_lock( cache );
|
|
|
|
|
2009-05-20 14:43:24 +00:00
|
|
|
hr = CreateAssemblyEnum(&asmenum, NULL, asmname, ASM_CACHE_GAC, NULL);
|
|
|
|
if (FAILED(hr))
|
|
|
|
goto done;
|
|
|
|
|
2013-05-04 20:21:39 +00:00
|
|
|
for (;;)
|
2009-05-20 14:43:24 +00:00
|
|
|
{
|
2013-05-04 20:21:39 +00:00
|
|
|
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;
|
2009-05-20 14:43:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!pAsmInfo)
|
|
|
|
goto done;
|
|
|
|
|
2010-12-27 09:50:02 +00:00
|
|
|
hr = IAssemblyName_GetPath(next, pAsmInfo->pszCurrentAssemblyPathBuf, &pAsmInfo->cchBuf);
|
|
|
|
|
2009-05-20 14:43:24 +00:00
|
|
|
pAsmInfo->dwAssemblyFlags = ASSEMBLYINFO_FLAG_INSTALLED;
|
|
|
|
|
|
|
|
done:
|
|
|
|
IAssemblyName_Release(asmname);
|
|
|
|
if (next) IAssemblyName_Release(next);
|
|
|
|
if (asmenum) IAssemblyEnum_Release(asmenum);
|
2012-05-19 09:41:07 +00:00
|
|
|
cache_unlock( cache );
|
2009-05-20 14:43:24 +00:00
|
|
|
return hr;
|
2008-09-10 08:47:30 +00:00
|
|
|
}
|
|
|
|
|
2015-03-21 12:21:40 +00:00
|
|
|
static const IAssemblyCacheItemVtbl AssemblyCacheItemVtbl;
|
|
|
|
|
2008-09-10 08:47:30 +00:00
|
|
|
static HRESULT WINAPI IAssemblyCacheImpl_CreateAssemblyCacheItem(IAssemblyCache *iface,
|
|
|
|
DWORD dwFlags,
|
|
|
|
PVOID pvReserved,
|
|
|
|
IAssemblyCacheItem **ppAsmItem,
|
|
|
|
LPCWSTR pszAssemblyName)
|
|
|
|
{
|
2015-03-21 12:21:40 +00:00
|
|
|
IAssemblyCacheItemImpl *item;
|
|
|
|
|
|
|
|
FIXME("(%p, %d, %p, %p, %s) semi-stub!\n", iface, dwFlags, pvReserved,
|
2008-09-10 08:47:30 +00:00
|
|
|
ppAsmItem, debugstr_w(pszAssemblyName));
|
|
|
|
|
2015-03-21 12:21:40 +00:00
|
|
|
if (!ppAsmItem)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
|
|
|
*ppAsmItem = NULL;
|
|
|
|
|
2018-03-09 12:07:30 +00:00
|
|
|
if (!(item = heap_alloc(sizeof(*item)))) return E_OUTOFMEMORY;
|
2015-03-21 12:21:40 +00:00
|
|
|
|
|
|
|
item->IAssemblyCacheItem_iface.lpVtbl = &AssemblyCacheItemVtbl;
|
|
|
|
item->ref = 1;
|
|
|
|
|
|
|
|
*ppAsmItem = &item->IAssemblyCacheItem_iface;
|
|
|
|
return S_OK;
|
2008-09-10 08:47:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IAssemblyCacheImpl_CreateAssemblyScavenger(IAssemblyCache *iface,
|
|
|
|
IUnknown **ppUnkReserved)
|
|
|
|
{
|
|
|
|
FIXME("(%p, %p) stub!\n", iface, ppUnkReserved);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
2013-05-04 20:21:39 +00:00
|
|
|
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;
|
2019-10-26 21:56:11 +00:00
|
|
|
DWORD len = lstrlenW( filename );
|
2013-05-04 20:21:39 +00:00
|
|
|
HRESULT hr = S_OK;
|
|
|
|
|
2018-03-09 12:07:30 +00:00
|
|
|
if (!(src_file = heap_alloc( (src_len + len + 1) * sizeof(WCHAR) )))
|
2013-05-04 20:21:39 +00:00
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
memcpy( src_file, src_dir, src_len * sizeof(WCHAR) );
|
2019-10-26 21:56:11 +00:00
|
|
|
lstrcpyW( src_file + src_len, filename );
|
2013-05-04 20:21:39 +00:00
|
|
|
|
2018-03-09 12:07:30 +00:00
|
|
|
if (!(dst_file = heap_alloc( (dst_len + len + 1) * sizeof(WCHAR) )))
|
2013-05-04 20:21:39 +00:00
|
|
|
{
|
2018-03-09 12:07:30 +00:00
|
|
|
heap_free( src_file );
|
2013-05-04 20:21:39 +00:00
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
memcpy( dst_file, dst_dir, dst_len * sizeof(WCHAR) );
|
2019-10-26 21:56:11 +00:00
|
|
|
lstrcpyW( dst_file + dst_len, filename );
|
2013-05-04 20:21:39 +00:00
|
|
|
|
|
|
|
if (!CopyFileW( src_file, dst_file, FALSE )) hr = HRESULT_FROM_WIN32( GetLastError() );
|
2018-03-09 12:07:30 +00:00
|
|
|
heap_free( src_file );
|
|
|
|
heap_free( dst_file );
|
2013-05-04 20:21:39 +00:00
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2008-09-10 08:47:30 +00:00
|
|
|
static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface,
|
|
|
|
DWORD dwFlags,
|
|
|
|
LPCWSTR pszManifestFilePath,
|
|
|
|
LPCFUSION_INSTALL_REFERENCE pRefData)
|
|
|
|
{
|
2013-05-04 20:21:39 +00:00
|
|
|
static const WCHAR format[] =
|
|
|
|
{'%','s','\\','%','s','\\','%','s','_','_','%','s','\\',0};
|
|
|
|
static const WCHAR format_v40[] =
|
|
|
|
{'%','s','\\','%','s','\\','v','4','.','0','_','%','s','_','_','%','s','\\',0};
|
2012-05-19 09:41:07 +00:00
|
|
|
static const WCHAR ext_exe[] = {'.','e','x','e',0};
|
|
|
|
static const WCHAR ext_dll[] = {'.','d','l','l',0};
|
|
|
|
IAssemblyCacheImpl *cache = impl_from_IAssemblyCache(iface);
|
2008-09-10 08:47:30 +00:00
|
|
|
ASSEMBLY *assembly;
|
2013-05-04 20:21:39 +00:00
|
|
|
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;
|
2018-10-01 11:49:44 +00:00
|
|
|
DWORD i, count = 0, src_len, dst_len = ARRAY_SIZE(format_v40);
|
2008-09-10 08:47:30 +00:00
|
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
TRACE("(%p, %d, %s, %p)\n", iface, dwFlags,
|
|
|
|
debugstr_w(pszManifestFilePath), pRefData);
|
|
|
|
|
|
|
|
if (!pszManifestFilePath || !*pszManifestFilePath)
|
|
|
|
return E_INVALIDARG;
|
|
|
|
|
2019-10-26 21:56:11 +00:00
|
|
|
if (!(extension = wcsrchr(pszManifestFilePath, '.')))
|
2008-09-10 08:47:30 +00:00
|
|
|
return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
|
|
|
|
|
2013-05-04 20:21:39 +00:00
|
|
|
if (lstrcmpiW(extension, ext_exe) && lstrcmpiW(extension, ext_dll))
|
2008-09-10 08:47:30 +00:00
|
|
|
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;
|
|
|
|
|
2013-05-04 20:21:39 +00:00
|
|
|
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;
|
|
|
|
|
2012-05-19 09:41:07 +00:00
|
|
|
cache_lock( cache );
|
|
|
|
|
2013-05-04 20:21:39 +00:00
|
|
|
architecture = assembly_get_architecture(assembly);
|
|
|
|
get_assembly_directory(asmdir, MAX_PATH, clr_version, architecture);
|
2008-09-10 08:47:30 +00:00
|
|
|
|
2019-10-26 21:56:11 +00:00
|
|
|
dst_len += lstrlenW(asmdir) + lstrlenW(name) + lstrlenW(version) + lstrlenW(token);
|
2018-03-09 12:07:30 +00:00
|
|
|
if (!(dst_dir = heap_alloc(dst_len * sizeof(WCHAR))))
|
2013-05-04 20:21:39 +00:00
|
|
|
{
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if (!strcmp(clr_version, "v4.0.30319"))
|
2019-10-26 21:56:11 +00:00
|
|
|
dst_len = swprintf(dst_dir, format_v40, asmdir, name, version, token);
|
2013-05-04 20:21:39 +00:00
|
|
|
else
|
2019-10-26 21:56:11 +00:00
|
|
|
dst_len = swprintf(dst_dir, format, asmdir, name, version, token);
|
2008-09-10 08:47:30 +00:00
|
|
|
|
2013-05-04 20:21:39 +00:00
|
|
|
create_full_path(dst_dir);
|
2008-09-10 08:47:30 +00:00
|
|
|
|
|
|
|
hr = assembly_get_path(assembly, &asmpath);
|
|
|
|
if (FAILED(hr))
|
|
|
|
goto done;
|
|
|
|
|
2019-10-26 21:56:11 +00:00
|
|
|
if ((p = wcsrchr(asmpath, '\\')))
|
2013-05-04 20:21:39 +00:00
|
|
|
{
|
|
|
|
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;
|
2008-09-10 08:47:30 +00:00
|
|
|
|
2013-05-04 20:21:39 +00:00
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
hr = copy_file(src_dir, src_len, dst_dir, dst_len, external_files[i]);
|
|
|
|
if (FAILED(hr))
|
|
|
|
break;
|
|
|
|
}
|
2008-09-10 08:47:30 +00:00
|
|
|
|
|
|
|
done:
|
2018-03-09 12:07:30 +00:00
|
|
|
heap_free(name);
|
|
|
|
heap_free(token);
|
|
|
|
heap_free(version);
|
|
|
|
heap_free(asmpath);
|
|
|
|
heap_free(dst_dir);
|
|
|
|
for (i = 0; i < count; i++) heap_free(external_files[i]);
|
|
|
|
heap_free(external_files);
|
2008-09-10 08:47:30 +00:00
|
|
|
assembly_release(assembly);
|
2012-05-19 09:41:07 +00:00
|
|
|
cache_unlock( cache );
|
2008-09-10 08:47:30 +00:00
|
|
|
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;
|
|
|
|
|
2018-03-09 12:07:30 +00:00
|
|
|
if (!(cache = heap_alloc(sizeof(*cache)))) return E_OUTOFMEMORY;
|
2008-09-10 08:47:30 +00:00
|
|
|
|
2010-12-27 09:50:02 +00:00
|
|
|
cache->IAssemblyCache_iface.lpVtbl = &AssemblyCacheVtbl;
|
2008-09-10 08:47:30 +00:00
|
|
|
cache->ref = 1;
|
2012-05-19 09:41:07 +00:00
|
|
|
cache->lock = CreateMutexW( NULL, FALSE, cache_mutex_nameW );
|
|
|
|
if (!cache->lock)
|
|
|
|
{
|
2018-03-09 12:07:30 +00:00
|
|
|
heap_free( cache );
|
2012-05-19 09:41:07 +00:00
|
|
|
return HRESULT_FROM_WIN32( GetLastError() );
|
|
|
|
}
|
2010-12-27 09:50:02 +00:00
|
|
|
*ppAsmCache = &cache->IAssemblyCache_iface;
|
2008-09-10 08:47:30 +00:00
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* IAssemblyCacheItem */
|
|
|
|
|
2010-12-27 09:50:02 +00:00
|
|
|
static inline IAssemblyCacheItemImpl *impl_from_IAssemblyCacheItem(IAssemblyCacheItem *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, IAssemblyCacheItemImpl, IAssemblyCacheItem_iface);
|
|
|
|
}
|
|
|
|
|
2008-09-10 08:47:30 +00:00
|
|
|
static HRESULT WINAPI IAssemblyCacheItemImpl_QueryInterface(IAssemblyCacheItem *iface,
|
|
|
|
REFIID riid, LPVOID *ppobj)
|
|
|
|
{
|
2010-12-27 09:50:02 +00:00
|
|
|
IAssemblyCacheItemImpl *This = impl_from_IAssemblyCacheItem(iface);
|
2008-09-10 08:47:30 +00:00
|
|
|
|
|
|
|
TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj);
|
|
|
|
|
|
|
|
*ppobj = NULL;
|
|
|
|
|
|
|
|
if (IsEqualIID(riid, &IID_IUnknown) ||
|
|
|
|
IsEqualIID(riid, &IID_IAssemblyCacheItem))
|
|
|
|
{
|
2013-05-04 20:21:39 +00:00
|
|
|
IAssemblyCacheItem_AddRef(iface);
|
2015-07-19 13:16:45 +00:00
|
|
|
*ppobj = &This->IAssemblyCacheItem_iface;
|
2008-09-10 08:47:30 +00:00
|
|
|
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)
|
|
|
|
{
|
2010-12-27 09:50:02 +00:00
|
|
|
IAssemblyCacheItemImpl *This = impl_from_IAssemblyCacheItem(iface);
|
2008-09-10 08:47:30 +00:00
|
|
|
ULONG refCount = InterlockedIncrement(&This->ref);
|
|
|
|
|
|
|
|
TRACE("(%p)->(ref before = %u)\n", This, refCount - 1);
|
|
|
|
|
|
|
|
return refCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG WINAPI IAssemblyCacheItemImpl_Release(IAssemblyCacheItem *iface)
|
|
|
|
{
|
2010-12-27 09:50:02 +00:00
|
|
|
IAssemblyCacheItemImpl *This = impl_from_IAssemblyCacheItem(iface);
|
2008-09-10 08:47:30 +00:00
|
|
|
ULONG refCount = InterlockedDecrement(&This->ref);
|
|
|
|
|
|
|
|
TRACE("(%p)->(ref before = %u)\n", This, refCount + 1);
|
|
|
|
|
|
|
|
if (!refCount)
|
2018-03-09 12:07:30 +00:00
|
|
|
heap_free(This);
|
2008-09-10 08:47:30 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
};
|