diff --git a/dlls/fusion/asmname.c b/dlls/fusion/asmname.c index 16cd7b0ceb3..81a5b82ebbf 100644 --- a/dlls/fusion/asmname.c +++ b/dlls/fusion/asmname.c @@ -29,13 +29,40 @@ #include "ole2.h" #include "guiddef.h" #include "fusion.h" +#include "corerror.h" + #include "wine/debug.h" +#include "wine/unicode.h" 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 { const IAssemblyNameVtbl *lpIAssemblyNameVtbl; + LPWSTR displayname; + LPWSTR name; + LPWSTR culture; + + BYTE version[4]; + DWORD versize; + + BYTE pubkey[8]; + BOOL haspubkey; + LONG ref; } IAssemblyNameImpl; @@ -78,7 +105,12 @@ static ULONG WINAPI IAssemblyNameImpl_Release(IAssemblyName *iface) TRACE("(%p)->(ref before = %u)\n", This, refCount + 1); if (!refCount) + { + HeapFree(GetProcessHeap(), 0, This->displayname); + HeapFree(GetProcessHeap(), 0, This->name); + HeapFree(GetProcessHeap(), 0, This->culture); HeapFree(GetProcessHeap(), 0, This); + } return refCount; } @@ -97,8 +129,84 @@ static HRESULT WINAPI IAssemblyNameImpl_GetProperty(IAssemblyName *iface, LPVOID pvProperty, LPDWORD pcbProperty) { - FIXME("(%p, %d, %p, %p) stub!\n", iface, PropertyId, pvProperty, pcbProperty); - return E_NOTIMPL; + IAssemblyNameImpl *name = (IAssemblyNameImpl *)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((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) @@ -112,10 +220,18 @@ static HRESULT WINAPI IAssemblyNameImpl_GetDisplayName(IAssemblyName *iface, LPDWORD pccDisplayName, 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); - 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, @@ -140,16 +256,41 @@ static HRESULT WINAPI IAssemblyNameImpl_GetName(IAssemblyName *iface, LPDWORD lpcwBuffer, WCHAR *pwzName) { - FIXME("(%p, %p, %p) stub!\n", iface, lpcwBuffer, pwzName); - return E_NOTIMPL; + IAssemblyNameImpl *name = (IAssemblyNameImpl *)iface; + + 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) { - FIXME("(%p, %p, %p) stub!\n", iface, pdwVersionHi, pdwVersionLow); - return E_NOTIMPL; + IAssemblyNameImpl *name = (IAssemblyNameImpl *)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, @@ -181,3 +322,204 @@ static const IAssemblyNameVtbl AssemblyNameVtbl = { IAssemblyNameImpl_IsEqual, 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; +} diff --git a/dlls/fusion/fusion.c b/dlls/fusion/fusion.c index 999cb9200b0..cabe68e5c6c 100644 --- a/dlls/fusion/fusion.c +++ b/dlls/fusion/fusion.c @@ -65,19 +65,6 @@ HRESULT WINAPI CreateAssemblyEnum(IAssemblyEnum **pEnum, IUnknown *pUnkReserved, 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.@) */ diff --git a/include/corerror.h b/include/corerror.h index 9845cda8259..8a04699bd29 100644 --- a/include/corerror.h +++ b/include/corerror.h @@ -22,12 +22,12 @@ #include #ifndef FACILITY_URT - #define FACILITY_URT 0x13 +#define FACILITY_URT 0x13 #endif #ifndef EMAKEHR - #define SMAKEHR(val) MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_URT, val) - #define EMAKEHR(val) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_URT, val) +#define SMAKEHR(val) MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_URT, val) +#define EMAKEHR(val) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_URT, val) #endif #define COR_E_ARGUMENT E_INVALIDARG @@ -119,5 +119,6 @@ #define COR_E_HOSTPROTECTION EMAKEHR(0x1640L) #define COR_E_ILLEGAL_REENTRANCY EMAKEHR(0x1641L) +#define FUSION_E_INVALID_NAME EMAKEHR(0x1047) #endif /* __WINE_CORERROR_H */