2008-09-10 08:47:30 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2013-12-23 18:16:01 +00:00
|
|
|
#include "fusionpriv.h"
|
2013-01-24 23:00:42 +00:00
|
|
|
|
2010-12-27 09:50:02 +00:00
|
|
|
#include <assert.h>
|
2014-01-23 11:22:13 +00:00
|
|
|
#include <winuser.h>
|
2008-09-10 08:47:30 +00:00
|
|
|
|
|
|
|
typedef struct {
|
2012-01-25 19:09:23 +00:00
|
|
|
IAssemblyName IAssemblyName_iface;
|
2008-09-10 08:47:30 +00:00
|
|
|
|
2010-12-27 09:50:02 +00:00
|
|
|
LPWSTR path;
|
|
|
|
|
2008-09-10 08:47:30 +00:00
|
|
|
LPWSTR displayname;
|
|
|
|
LPWSTR name;
|
|
|
|
LPWSTR culture;
|
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
|
|
|
LPWSTR procarch;
|
2008-09-10 08:47:30 +00:00
|
|
|
|
2009-05-20 14:43:24 +00:00
|
|
|
WORD version[4];
|
2008-09-10 08:47:30 +00:00
|
|
|
DWORD versize;
|
|
|
|
|
|
|
|
BYTE pubkey[8];
|
|
|
|
BOOL haspubkey;
|
|
|
|
|
|
|
|
LONG ref;
|
|
|
|
} IAssemblyNameImpl;
|
|
|
|
|
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 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
|
|
|
|
|
2012-01-25 19:09:23 +00:00
|
|
|
static inline IAssemblyNameImpl *impl_from_IAssemblyName(IAssemblyName *iface)
|
|
|
|
{
|
|
|
|
return CONTAINING_RECORD(iface, IAssemblyNameImpl, IAssemblyName_iface);
|
|
|
|
}
|
|
|
|
|
2008-09-10 08:47:30 +00:00
|
|
|
static HRESULT WINAPI IAssemblyNameImpl_QueryInterface(IAssemblyName *iface,
|
|
|
|
REFIID riid, LPVOID *ppobj)
|
|
|
|
{
|
2012-01-25 19:09:23 +00:00
|
|
|
IAssemblyNameImpl *This = impl_from_IAssemblyName(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_IAssemblyName))
|
|
|
|
{
|
2013-05-04 20:21:39 +00:00
|
|
|
IAssemblyName_AddRef(iface);
|
2008-09-10 08:47:30 +00:00
|
|
|
*ppobj = This;
|
|
|
|
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)
|
|
|
|
{
|
2012-01-25 19:09:23 +00:00
|
|
|
IAssemblyNameImpl *This = impl_from_IAssemblyName(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 IAssemblyNameImpl_Release(IAssemblyName *iface)
|
|
|
|
{
|
2012-01-25 19:09:23 +00:00
|
|
|
IAssemblyNameImpl *This = impl_from_IAssemblyName(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)
|
|
|
|
{
|
2010-12-27 09:50:02 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, This->path);
|
2008-09-10 08:47:30 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, This->displayname);
|
|
|
|
HeapFree(GetProcessHeap(), 0, This->name);
|
|
|
|
HeapFree(GetProcessHeap(), 0, This->culture);
|
2012-01-25 19:09:23 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, This->procarch);
|
2008-09-10 08:47:30 +00:00
|
|
|
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)
|
|
|
|
{
|
2012-01-25 19:09:23 +00:00
|
|
|
IAssemblyNameImpl *name = impl_from_IAssemblyName(iface);
|
2008-09-10 08:47:30 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2009-01-17 19:56:32 +00:00
|
|
|
lstrcpyW(pvProperty, name->name);
|
2008-09-10 08:47:30 +00:00
|
|
|
*pcbProperty = (lstrlenW(name->name) + 1) * 2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ASM_NAME_MAJOR_VERSION:
|
|
|
|
*pcbProperty = 0;
|
2009-05-20 14:43:24 +00:00
|
|
|
*((WORD *)pvProperty) = name->version[0];
|
2008-09-10 08:47:30 +00:00
|
|
|
if (name->versize >= 1)
|
|
|
|
*pcbProperty = sizeof(WORD);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ASM_NAME_MINOR_VERSION:
|
|
|
|
*pcbProperty = 0;
|
2009-05-20 14:43:24 +00:00
|
|
|
*((WORD *)pvProperty) = name->version[1];
|
2008-09-10 08:47:30 +00:00
|
|
|
if (name->versize >= 2)
|
|
|
|
*pcbProperty = sizeof(WORD);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ASM_NAME_BUILD_NUMBER:
|
|
|
|
*pcbProperty = 0;
|
2009-05-20 14:43:24 +00:00
|
|
|
*((WORD *)pvProperty) = name->version[2];
|
2008-09-10 08:47:30 +00:00
|
|
|
if (name->versize >= 3)
|
|
|
|
*pcbProperty = sizeof(WORD);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ASM_NAME_REVISION_NUMBER:
|
|
|
|
*pcbProperty = 0;
|
2009-05-20 14:43:24 +00:00
|
|
|
*((WORD *)pvProperty) = name->version[3];
|
2008-09-10 08:47:30 +00:00
|
|
|
if (name->versize >= 4)
|
|
|
|
*pcbProperty = sizeof(WORD);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ASM_NAME_CULTURE:
|
|
|
|
*pcbProperty = 0;
|
|
|
|
if (name->culture)
|
|
|
|
{
|
2009-01-17 19:56:32 +00:00
|
|
|
lstrcpyW(pvProperty, name->culture);
|
2008-09-10 08:47:30 +00:00
|
|
|
*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)
|
|
|
|
{
|
2012-01-25 19:09:23 +00:00
|
|
|
IAssemblyNameImpl *name = impl_from_IAssemblyName(iface);
|
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
|
|
|
WCHAR verstr[30];
|
|
|
|
DWORD size;
|
|
|
|
LPWSTR cultureval = 0;
|
|
|
|
|
|
|
|
static const WCHAR equals[] = {'=',0};
|
2008-09-10 08:47:30 +00:00
|
|
|
|
2009-05-20 14:43:24 +00:00
|
|
|
TRACE("(%p, %p, %p, %d)\n", iface, szDisplayName,
|
2008-09-10 08:47:30 +00:00
|
|
|
pccDisplayName, dwDisplayFlags);
|
|
|
|
|
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
|
|
|
if (dwDisplayFlags == 0)
|
|
|
|
{
|
|
|
|
if (!name->displayname || !*name->displayname)
|
|
|
|
return FUSION_E_INVALID_NAME;
|
|
|
|
|
|
|
|
size = min(*pccDisplayName, lstrlenW(name->displayname) + 1);
|
|
|
|
|
|
|
|
lstrcpynW(szDisplayName, name->displayname, size);
|
|
|
|
*pccDisplayName = size;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!name->name || !*name->name)
|
2008-09-10 08:47:30 +00:00
|
|
|
return FUSION_E_INVALID_NAME;
|
|
|
|
|
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
|
|
|
/* 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};
|
2013-05-04 20:21:39 +00:00
|
|
|
DWORD i;
|
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
|
|
|
|
|
|
|
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);
|
2008-09-10 08:47:30 +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
|
|
|
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;
|
2008-09-10 08:47:30 +00:00
|
|
|
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, %x%08x, %p, %d, %p)\n", iface,
|
|
|
|
debugstr_guid(refIID), pUnkReserved1, pUnkReserved2,
|
|
|
|
debugstr_w(szReserved), (DWORD)(llReserved >> 32), (DWORD)llReserved,
|
|
|
|
pvReserved, cbReserved, ppReserved);
|
|
|
|
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IAssemblyNameImpl_GetName(IAssemblyName *iface,
|
|
|
|
LPDWORD lpcwBuffer,
|
|
|
|
WCHAR *pwzName)
|
|
|
|
{
|
2012-01-25 19:09:23 +00:00
|
|
|
IAssemblyNameImpl *name = impl_from_IAssemblyName(iface);
|
2008-09-10 08:47:30 +00:00
|
|
|
|
|
|
|
TRACE("(%p, %p, %p)\n", iface, lpcwBuffer, pwzName);
|
|
|
|
|
|
|
|
if (!name->name)
|
|
|
|
{
|
|
|
|
*pwzName = '\0';
|
|
|
|
*lpcwBuffer = 0;
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
lstrcpyW(pwzName, name->name);
|
|
|
|
*lpcwBuffer = lstrlenW(pwzName) + 1;
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT WINAPI IAssemblyNameImpl_GetVersion(IAssemblyName *iface,
|
|
|
|
LPDWORD pdwVersionHi,
|
|
|
|
LPDWORD pdwVersionLow)
|
|
|
|
{
|
2012-01-25 19:09:23 +00:00
|
|
|
IAssemblyNameImpl *name = impl_from_IAssemblyName(iface);
|
2008-09-10 08:47:30 +00:00
|
|
|
|
|
|
|
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,
|
2013-05-04 20:21:39 +00:00
|
|
|
DWORD flags)
|
2008-09-10 08:47:30 +00:00
|
|
|
{
|
2013-05-04 20:21:39 +00:00
|
|
|
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;
|
2008-09-10 08:47:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
};
|
|
|
|
|
2010-12-27 09:50:02 +00:00
|
|
|
/* Internal methods */
|
2012-01-25 19:09:23 +00:00
|
|
|
static inline IAssemblyNameImpl *unsafe_impl_from_IAssemblyName(IAssemblyName *iface)
|
2010-12-27 09:50:02 +00:00
|
|
|
{
|
2012-01-25 19:09:23 +00:00
|
|
|
assert(iface->lpVtbl == &AssemblyNameVtbl);
|
2010-12-27 09:50:02 +00:00
|
|
|
|
2012-01-25 19:09:23 +00:00
|
|
|
return impl_from_IAssemblyName(iface);
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT IAssemblyName_SetPath(IAssemblyName *iface, LPCWSTR path)
|
|
|
|
{
|
|
|
|
IAssemblyNameImpl *name = unsafe_impl_from_IAssemblyName(iface);
|
2010-12-27 09:50:02 +00:00
|
|
|
|
|
|
|
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;
|
2012-01-25 19:09:23 +00:00
|
|
|
IAssemblyNameImpl *name = unsafe_impl_from_IAssemblyName(iface);
|
2010-12-27 09:50:02 +00:00
|
|
|
|
|
|
|
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 HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2008-09-10 08:47:30 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-12-27 09:50:02 +00:00
|
|
|
static HRESULT parse_culture(IAssemblyNameImpl *name, LPCWSTR culture)
|
2008-09-10 08:47:30 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-12-27 09:50:02 +00:00
|
|
|
static HRESULT parse_pubkey(IAssemblyNameImpl *name, LPCWSTR pubkey)
|
2008-09-10 08:47:30 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
BYTE val;
|
2013-05-04 20:21:39 +00:00
|
|
|
static const WCHAR nullstr[] = {'n','u','l','l',0};
|
|
|
|
|
|
|
|
if(lstrcmpiW(pubkey, nullstr) == 0)
|
|
|
|
return FUSION_E_PRIVATE_ASM_DISALLOWED;
|
2008-09-10 08:47:30 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-05-04 20:21:39 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-09-10 08:47:30 +00:00
|
|
|
static HRESULT parse_display_name(IAssemblyNameImpl *name, LPCWSTR szAssemblyName)
|
|
|
|
{
|
2013-05-04 20:21:39 +00:00
|
|
|
LPWSTR str, save, ptr, ptr2, value;
|
2008-09-10 08:47:30 +00:00
|
|
|
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)
|
2012-01-25 19:09:23 +00:00
|
|
|
{
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
goto done;
|
|
|
|
}
|
2008-09-10 08:47:30 +00:00
|
|
|
|
2010-12-27 09:50:02 +00:00
|
|
|
ptr = strchrW(str, ',');
|
2008-09-10 08:47:30 +00:00
|
|
|
if (ptr) *ptr = '\0';
|
2010-12-27 09:50:02 +00:00
|
|
|
|
|
|
|
/* no ',' but ' ' only */
|
|
|
|
if( !ptr && strchrW(str, ' ') )
|
|
|
|
{
|
|
|
|
hr = FUSION_E_INVALID_NAME;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2008-09-10 08:47:30 +00:00
|
|
|
name->name = strdupW(str);
|
|
|
|
if (!name->name)
|
2012-01-25 19:09:23 +00:00
|
|
|
{
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
goto done;
|
|
|
|
}
|
2008-09-10 08:47:30 +00:00
|
|
|
|
|
|
|
if (!ptr)
|
|
|
|
goto done;
|
|
|
|
|
2013-05-04 20:21:39 +00:00
|
|
|
str = ptr + 1;
|
2008-09-10 08:47:30 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-05-04 20:21:39 +00:00
|
|
|
if (!(ptr2 = strchrW(ptr, ',')))
|
2008-09-10 08:47:30 +00:00
|
|
|
{
|
|
|
|
if (!(ptr2 = strchrW(ptr, '\0')))
|
|
|
|
{
|
|
|
|
hr = FUSION_E_INVALID_NAME;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
done = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*ptr2 = '\0';
|
2013-05-04 20:21:39 +00:00
|
|
|
if (!(value = parse_value( ptr, ptr2 - ptr )))
|
|
|
|
{
|
|
|
|
hr = FUSION_E_INVALID_NAME;
|
|
|
|
goto done;
|
|
|
|
}
|
2009-05-20 14:43:24 +00:00
|
|
|
while (*str == ' ') str++;
|
|
|
|
|
2013-05-04 20:21:39 +00:00
|
|
|
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))
|
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
|
|
|
{
|
2013-05-04 20:21:39 +00:00
|
|
|
name->procarch = value;
|
|
|
|
value = NULL;
|
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
|
|
|
}
|
2013-05-04 20:21:39 +00:00
|
|
|
HeapFree( GetProcessHeap(), 0, value );
|
2008-09-10 08:47:30 +00:00
|
|
|
|
|
|
|
if (FAILED(hr))
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
str = ptr2 + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
HeapFree(GetProcessHeap(), 0, save);
|
2010-03-05 18:30:07 +00:00
|
|
|
if (FAILED(hr))
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, name->displayname);
|
|
|
|
HeapFree(GetProcessHeap(), 0, name->name);
|
|
|
|
}
|
2008-09-10 08:47:30 +00:00
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************
|
|
|
|
* CreateAssemblyNameObject (FUSION.@)
|
|
|
|
*/
|
|
|
|
HRESULT WINAPI CreateAssemblyNameObject(LPASSEMBLYNAME *ppAssemblyNameObj,
|
|
|
|
LPCWSTR szAssemblyName, DWORD dwFlags,
|
|
|
|
LPVOID pvReserved)
|
|
|
|
{
|
|
|
|
IAssemblyNameImpl *name;
|
|
|
|
HRESULT hr;
|
|
|
|
|
2012-05-19 09:41:07 +00:00
|
|
|
TRACE("(%p, %s, %08x, %p)\n", ppAssemblyNameObj,
|
2008-09-10 08:47:30 +00:00
|
|
|
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;
|
|
|
|
|
2012-01-25 19:09:23 +00:00
|
|
|
name->IAssemblyName_iface.lpVtbl = &AssemblyNameVtbl;
|
2008-09-10 08:47:30 +00:00
|
|
|
name->ref = 1;
|
|
|
|
|
|
|
|
hr = parse_display_name(name, szAssemblyName);
|
|
|
|
if (FAILED(hr))
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, name);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2012-01-25 19:09:23 +00:00
|
|
|
*ppAssemblyNameObj = &name->IAssemblyName_iface;
|
2008-09-10 08:47:30 +00:00
|
|
|
|
|
|
|
return S_OK;
|
|
|
|
}
|