fusion: Add initial implementation of IAssemblyName.

This commit is contained in:
James Hawkins 2008-06-29 18:23:22 -05:00 committed by Alexandre Julliard
parent 9ac630e058
commit 7b1dde9d20
3 changed files with 354 additions and 24 deletions

View File

@ -29,13 +29,40 @@
#include "ole2.h" #include "ole2.h"
#include "guiddef.h" #include "guiddef.h"
#include "fusion.h" #include "fusion.h"
#include "corerror.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(fusion); WINE_DEFAULT_DEBUG_CHANNEL(fusion);
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;
}
typedef struct { typedef struct {
const IAssemblyNameVtbl *lpIAssemblyNameVtbl; const IAssemblyNameVtbl *lpIAssemblyNameVtbl;
LPWSTR displayname;
LPWSTR name;
LPWSTR culture;
BYTE version[4];
DWORD versize;
BYTE pubkey[8];
BOOL haspubkey;
LONG ref; LONG ref;
} IAssemblyNameImpl; } IAssemblyNameImpl;
@ -78,7 +105,12 @@ static ULONG WINAPI IAssemblyNameImpl_Release(IAssemblyName *iface)
TRACE("(%p)->(ref before = %u)\n", This, refCount + 1); TRACE("(%p)->(ref before = %u)\n", This, refCount + 1);
if (!refCount) if (!refCount)
{
HeapFree(GetProcessHeap(), 0, This->displayname);
HeapFree(GetProcessHeap(), 0, This->name);
HeapFree(GetProcessHeap(), 0, This->culture);
HeapFree(GetProcessHeap(), 0, This); HeapFree(GetProcessHeap(), 0, This);
}
return refCount; return refCount;
} }
@ -97,8 +129,84 @@ static HRESULT WINAPI IAssemblyNameImpl_GetProperty(IAssemblyName *iface,
LPVOID pvProperty, LPVOID pvProperty,
LPDWORD pcbProperty) LPDWORD pcbProperty)
{ {
FIXME("(%p, %d, %p, %p) stub!\n", iface, PropertyId, pvProperty, pcbProperty); IAssemblyNameImpl *name = (IAssemblyNameImpl *)iface;
return E_NOTIMPL;
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((LPWSTR)pvProperty, name->name);
*pcbProperty = (lstrlenW(name->name) + 1) * 2;
}
break;
case ASM_NAME_MAJOR_VERSION:
*pcbProperty = 0;
*((LPDWORD)pvProperty) = name->version[0];
if (name->versize >= 1)
*pcbProperty = sizeof(WORD);
break;
case ASM_NAME_MINOR_VERSION:
*pcbProperty = 0;
*((LPDWORD)pvProperty) = name->version[1];
if (name->versize >= 2)
*pcbProperty = sizeof(WORD);
break;
case ASM_NAME_BUILD_NUMBER:
*pcbProperty = 0;
*((LPDWORD)pvProperty) = name->version[2];
if (name->versize >= 3)
*pcbProperty = sizeof(WORD);
break;
case ASM_NAME_REVISION_NUMBER:
*pcbProperty = 0;
*((LPDWORD)pvProperty) = name->version[3];
if (name->versize >= 4)
*pcbProperty = sizeof(WORD);
break;
case ASM_NAME_CULTURE:
*pcbProperty = 0;
if (name->culture)
{
lstrcpyW((LPWSTR)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) static HRESULT WINAPI IAssemblyNameImpl_Finalize(IAssemblyName *iface)
@ -112,10 +220,18 @@ static HRESULT WINAPI IAssemblyNameImpl_GetDisplayName(IAssemblyName *iface,
LPDWORD pccDisplayName, LPDWORD pccDisplayName,
DWORD dwDisplayFlags) DWORD dwDisplayFlags)
{ {
FIXME("(%p, %s, %p, %d) stub!\n", iface, debugstr_w(szDisplayName), IAssemblyNameImpl *name = (IAssemblyNameImpl *)iface;
TRACE("(%p, %s, %p, %d)\n", iface, debugstr_w(szDisplayName),
pccDisplayName, dwDisplayFlags); pccDisplayName, dwDisplayFlags);
return E_NOTIMPL; if (!name->displayname || !*name->displayname)
return FUSION_E_INVALID_NAME;
lstrcpyW(szDisplayName, name->displayname);
*pccDisplayName = lstrlenW(szDisplayName) + 1;
return S_OK;
} }
static HRESULT WINAPI IAssemblyNameImpl_Reserved(IAssemblyName *iface, static HRESULT WINAPI IAssemblyNameImpl_Reserved(IAssemblyName *iface,
@ -140,16 +256,41 @@ static HRESULT WINAPI IAssemblyNameImpl_GetName(IAssemblyName *iface,
LPDWORD lpcwBuffer, LPDWORD lpcwBuffer,
WCHAR *pwzName) WCHAR *pwzName)
{ {
FIXME("(%p, %p, %p) stub!\n", iface, lpcwBuffer, pwzName); IAssemblyNameImpl *name = (IAssemblyNameImpl *)iface;
return E_NOTIMPL;
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, static HRESULT WINAPI IAssemblyNameImpl_GetVersion(IAssemblyName *iface,
LPDWORD pdwVersionHi, LPDWORD pdwVersionHi,
LPDWORD pdwVersionLow) LPDWORD pdwVersionLow)
{ {
FIXME("(%p, %p, %p) stub!\n", iface, pdwVersionHi, pdwVersionLow); IAssemblyNameImpl *name = (IAssemblyNameImpl *)iface;
return E_NOTIMPL;
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, static HRESULT WINAPI IAssemblyNameImpl_IsEqual(IAssemblyName *iface,
@ -181,3 +322,204 @@ static const IAssemblyNameVtbl AssemblyNameVtbl = {
IAssemblyNameImpl_IsEqual, IAssemblyNameImpl_IsEqual,
IAssemblyNameImpl_Clone IAssemblyNameImpl_Clone
}; };
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, LPWSTR culture)
{
static const WCHAR empty[] = {0};
if (lstrlenW(culture) == 2)
name->culture = strdupW(culture);
else
name->culture = strdupW(empty);
return S_OK;
}
#define CHARS_PER_PUBKEY 16
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, LPWSTR pubkey)
{
int i;
BYTE val;
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 HRESULT parse_display_name(IAssemblyNameImpl *name, LPCWSTR szAssemblyName)
{
LPWSTR str, save;
LPWSTR ptr, ptr2;
HRESULT hr = S_OK;
BOOL done = FALSE;
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};
if (!szAssemblyName)
return S_OK;
name->displayname = strdupW(szAssemblyName);
if (!name->displayname)
return E_OUTOFMEMORY;
str = strdupW(szAssemblyName);
save = str;
if (!str)
return E_OUTOFMEMORY;
ptr = strstrW(str, separator);
if (ptr) *ptr = '\0';
name->name = strdupW(str);
if (!name->name)
return E_OUTOFMEMORY;
if (!ptr)
goto done;
str = ptr + 2;
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 = strstrW(ptr, separator)))
{
if (!(ptr2 = strchrW(ptr, '\0')))
{
hr = FUSION_E_INVALID_NAME;
goto done;
}
done = TRUE;
}
*ptr2 = '\0';
if (!lstrcmpW(str, version))
hr = parse_version(name, ptr);
else if (!lstrcmpW(str, culture))
hr = parse_culture(name, ptr);
else if (!lstrcmpW(str, pubkey))
hr = parse_pubkey(name, ptr);
if (FAILED(hr))
goto done;
str = ptr2 + 1;
}
done:
HeapFree(GetProcessHeap(), 0, save);
return hr;
}
/******************************************************************
* CreateAssemblyNameObject (FUSION.@)
*/
HRESULT WINAPI CreateAssemblyNameObject(LPASSEMBLYNAME *ppAssemblyNameObj,
LPCWSTR szAssemblyName, DWORD dwFlags,
LPVOID pvReserved)
{
IAssemblyNameImpl *name;
HRESULT hr;
TRACE("(%p, %s, %08x, %p) stub!\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->lpIAssemblyNameVtbl = &AssemblyNameVtbl;
name->ref = 1;
hr = parse_display_name(name, szAssemblyName);
if (FAILED(hr))
{
HeapFree(GetProcessHeap(), 0, name);
return hr;
}
*ppAssemblyNameObj = (IAssemblyName *)name;
return S_OK;
}

View File

@ -65,19 +65,6 @@ HRESULT WINAPI CreateAssemblyEnum(IAssemblyEnum **pEnum, IUnknown *pUnkReserved,
return E_NOTIMPL; return E_NOTIMPL;
} }
/******************************************************************
* CreateAssemblyNameObject (FUSION.@)
*/
HRESULT WINAPI CreateAssemblyNameObject(LPASSEMBLYNAME *ppAssemblyNameObj,
LPCWSTR szAssemblyName, DWORD dwFlags,
LPVOID pvReserved)
{
FIXME("(%p, %s, %08x, %p) stub!\n", ppAssemblyNameObj,
debugstr_w(szAssemblyName), dwFlags, pvReserved);
return E_NOTIMPL;
}
/****************************************************************** /******************************************************************
* CreateInstallReferenceEnum (FUSION.@) * CreateInstallReferenceEnum (FUSION.@)
*/ */

View File

@ -119,5 +119,6 @@
#define COR_E_HOSTPROTECTION EMAKEHR(0x1640L) #define COR_E_HOSTPROTECTION EMAKEHR(0x1640L)
#define COR_E_ILLEGAL_REENTRANCY EMAKEHR(0x1641L) #define COR_E_ILLEGAL_REENTRANCY EMAKEHR(0x1641L)
#define FUSION_E_INVALID_NAME EMAKEHR(0x1047)
#endif /* __WINE_CORERROR_H */ #endif /* __WINE_CORERROR_H */