Commit 282246ec authored by James Hawkins's avatar James Hawkins Committed by Alexandre Julliard

fusion: Implement IAssemblyCache::InstallAssembly.

parent d3afff85
...@@ -3,11 +3,12 @@ TOPOBJDIR = ../.. ...@@ -3,11 +3,12 @@ TOPOBJDIR = ../..
SRCDIR = @srcdir@ SRCDIR = @srcdir@
VPATH = @srcdir@ VPATH = @srcdir@
MODULE = fusion.dll MODULE = fusion.dll
IMPORTS = kernel32 IMPORTS = advapi32 dbghelp kernel32 shlwapi version
C_SRCS = \ C_SRCS = \
asmcache.c \ asmcache.c \
asmname.c \ asmname.c \
assembly.c \
fusion.c \ fusion.c \
fusion_main.c fusion_main.c
......
...@@ -19,18 +19,78 @@ ...@@ -19,18 +19,78 @@
*/ */
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h>
#define COBJMACROS #define COBJMACROS
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "winuser.h" #include "winuser.h"
#include "winver.h"
#include "wincrypt.h"
#include "winreg.h"
#include "shlwapi.h"
#include "dbghelp.h"
#include "ole2.h" #include "ole2.h"
#include "fusion.h" #include "fusion.h"
#include "corerror.h"
#include "fusionpriv.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(fusion); WINE_DEFAULT_DEBUG_CHANNEL(fusion);
static BOOL create_full_path(LPCSTR path)
{
LPSTR new_path;
BOOL ret = TRUE;
int len;
new_path = HeapAlloc(GetProcessHeap(), 0, lstrlenA(path) + 1);
if (!new_path)
return FALSE;
lstrcpyA(new_path, path);
while ((len = lstrlenA(new_path)) && new_path[len - 1] == '\\')
new_path[len - 1] = 0;
while (!CreateDirectoryA(new_path, NULL))
{
LPSTR slash;
DWORD last_error = GetLastError();
if(last_error == ERROR_ALREADY_EXISTS)
break;
if(last_error != ERROR_PATH_NOT_FOUND)
{
ret = FALSE;
break;
}
if(!(slash = strrchr(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;
}
/* IAssemblyCache */ /* IAssemblyCache */
typedef struct { typedef struct {
...@@ -130,10 +190,80 @@ static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface, ...@@ -130,10 +190,80 @@ static HRESULT WINAPI IAssemblyCacheImpl_InstallAssembly(IAssemblyCache *iface,
LPCWSTR pszManifestFilePath, LPCWSTR pszManifestFilePath,
LPCFUSION_INSTALL_REFERENCE pRefData) LPCFUSION_INSTALL_REFERENCE pRefData)
{ {
FIXME("(%p, %d, %s, %p) stub!\n", iface, dwFlags, ASSEMBLY *assembly;
LPSTR filename;
LPSTR name = NULL;
LPSTR token = NULL;
LPSTR version = NULL;
LPSTR asmpath = NULL;
CHAR path[MAX_PATH];
CHAR windir[MAX_PATH];
LPWSTR ext;
HRESULT hr;
static const WCHAR ext_exe[] = {'.','e','x','e',0};
static const WCHAR ext_dll[] = {'.','d','l','l',0};
TRACE("(%p, %d, %s, %p)\n", iface, dwFlags,
debugstr_w(pszManifestFilePath), pRefData); debugstr_w(pszManifestFilePath), pRefData);
return E_NOTIMPL; if (!pszManifestFilePath || !*pszManifestFilePath)
return E_INVALIDARG;
if (!(ext = strrchrW(pszManifestFilePath, '.')))
return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
if (lstrcmpW(ext, ext_exe) && lstrcmpW(ext, 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;
GetWindowsDirectoryA(windir, MAX_PATH);
FIXME("Ignoring assembly architecture!\n");
sprintf(path, "%s\\assembly\\GAC_MSIL\\%s\\%s__%s\\", windir, name,
version, token);
create_full_path(path);
hr = assembly_get_path(assembly, &asmpath);
if (FAILED(hr))
goto done;
filename = PathFindFileNameA(asmpath);
lstrcatA(path, filename);
if (!CopyFileA(asmpath, path, FALSE))
hr = HRESULT_FROM_WIN32(GetLastError());
done:
HeapFree(GetProcessHeap(), 0, name);
HeapFree(GetProcessHeap(), 0, token);
HeapFree(GetProcessHeap(), 0, version);
HeapFree(GetProcessHeap(), 0, asmpath);
assembly_release(assembly);
return hr;
} }
static const IAssemblyCacheVtbl AssemblyCacheVtbl = { static const IAssemblyCacheVtbl AssemblyCacheVtbl = {
......
/*
* 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>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
typedef struct
{
ULONG Signature;
USHORT MajorVersion;
USHORT MinorVersion;
ULONG Reserved;
ULONG VersionLength;
BYTE Version[12];
BYTE Flags;
WORD Streams;
} METADATAHDR;
#include <pshpack1.h>
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
{
DWORD ResolutionScope;
WORD Name;
WORD Namespace;
} TYPEREFTABLE;
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 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);
HRESULT assembly_release(ASSEMBLY *assembly);
HRESULT assembly_get_name(ASSEMBLY *assembly, LPSTR *name);
HRESULT assembly_get_path(ASSEMBLY *assembly, LPSTR *path);
HRESULT assembly_get_version(ASSEMBLY *assembly, LPSTR *version);
HRESULT assembly_get_architecture(ASSEMBLY *assembly, DWORD fixme);
HRESULT assembly_get_pubkey_token(ASSEMBLY *assembly, LPSTR *token);
#endif /* __WINE_FUSION_PRIVATE__ */
...@@ -853,6 +853,7 @@ static void test_InstallAssembly(void) ...@@ -853,6 +853,7 @@ static void test_InstallAssembly(void)
IAssemblyCache *cache; IAssemblyCache *cache;
HRESULT hr; HRESULT hr;
ULONG disp; ULONG disp;
DWORD attr;
static const WCHAR empty[] = {0}; static const WCHAR empty[] = {0};
static const WCHAR noext[] = {'f','i','l','e',0}; static const WCHAR noext[] = {'f','i','l','e',0};
...@@ -877,64 +878,44 @@ static void test_InstallAssembly(void) ...@@ -877,64 +878,44 @@ static void test_InstallAssembly(void)
/* NULL pszManifestFilePath */ /* NULL pszManifestFilePath */
hr = IAssemblyCache_InstallAssembly(cache, 0, NULL, NULL); hr = IAssemblyCache_InstallAssembly(cache, 0, NULL, NULL);
todo_wine ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
{
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
}
/* empty pszManifestFilePath */ /* empty pszManifestFilePath */
hr = IAssemblyCache_InstallAssembly(cache, 0, empty, NULL); hr = IAssemblyCache_InstallAssembly(cache, 0, empty, NULL);
todo_wine ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
{
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
}
/* pszManifestFilePath has no extension */ /* pszManifestFilePath has no extension */
hr = IAssemblyCache_InstallAssembly(cache, 0, noext, NULL); hr = IAssemblyCache_InstallAssembly(cache, 0, noext, NULL);
todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_NAME),
{ "Expected HRESULT_FROM_WIN32(ERROR_INVALID_NAME), got %08x\n", hr);
ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_NAME),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_NAME), got %08x\n", hr);
}
/* pszManifestFilePath has bad extension */ /* pszManifestFilePath has bad extension */
hr = IAssemblyCache_InstallAssembly(cache, 0, badext, NULL); hr = IAssemblyCache_InstallAssembly(cache, 0, badext, NULL);
todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_NAME),
{ "Expected HRESULT_FROM_WIN32(ERROR_INVALID_NAME), got %08x\n", hr);
ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_NAME),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_NAME), got %08x\n", hr);
}
/* pszManifestFilePath has dll extension */ /* pszManifestFilePath has dll extension */
hr = IAssemblyCache_InstallAssembly(cache, 0, dllext, NULL); hr = IAssemblyCache_InstallAssembly(cache, 0, dllext, NULL);
todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
{ "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr);
ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
"Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr);
}
/* pszManifestFilePath has exe extension */ /* pszManifestFilePath has exe extension */
hr = IAssemblyCache_InstallAssembly(cache, 0, exeext, NULL); hr = IAssemblyCache_InstallAssembly(cache, 0, exeext, NULL);
todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
{ "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr);
ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
"Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr);
}
/* empty file */ /* empty file */
hr = IAssemblyCache_InstallAssembly(cache, 0, testdll, NULL); hr = IAssemblyCache_InstallAssembly(cache, 0, testdll, NULL);
todo_wine ok(hr == COR_E_ASSEMBLYEXPECTED,
{ "Expected COR_E_ASSEMBLYEXPECTED, got %08x\n", hr);
ok(hr == COR_E_ASSEMBLYEXPECTED,
"Expected COR_E_ASSEMBLYEXPECTED, got %08x\n", hr);
}
/* wine assembly */ /* wine assembly */
hr = IAssemblyCache_InstallAssembly(cache, 0, winedll, NULL); hr = IAssemblyCache_InstallAssembly(cache, 0, winedll, NULL);
todo_wine ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
{
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); attr = GetFileAttributes("C:\\windows\\assembly\\GAC_MSIL\\wine\\"
} "1.0.0.0__2d03617b1c31e2f5/wine.dll");
ok(attr != INVALID_FILE_ATTRIBUTES, "Expected assembly to exist\n");
/* uninstall the assembly from the GAC */ /* uninstall the assembly from the GAC */
hr = IAssemblyCache_UninstallAssembly(cache, 0, wine, NULL, &disp); hr = IAssemblyCache_UninstallAssembly(cache, 0, wine, NULL, &disp);
...@@ -945,6 +926,12 @@ static void test_InstallAssembly(void) ...@@ -945,6 +926,12 @@ static void test_InstallAssembly(void)
"Expected IASSEMBLYCACHE_UNINSTALL_DISPOSITION_UNINSTALLED, got %d\n", disp); "Expected IASSEMBLYCACHE_UNINSTALL_DISPOSITION_UNINSTALLED, got %d\n", disp);
} }
/* FIXME: remove once UninstallAssembly is implemented */
DeleteFileA("C:\\windows\\assembly\\GAC_MSIL\\wine\\"
"1.0.0.0__2d03617b1c31e2f5\\wine.dll");
RemoveDirectoryA("C:\\windows\\assembly\\GAC_MSIL\\wine\\1.0.0.0__2d03617b1c31e2f5");
RemoveDirectoryA("C:\\windows\\assembly\\GAC_MSIL\\wine");
DeleteFileA("test.dll"); DeleteFileA("test.dll");
DeleteFileA("wine.dll"); DeleteFileA("wine.dll");
IAssemblyCache_Release(cache); IAssemblyCache_Release(cache);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment