Enumerate the assembly identity attributes of a given assembly

In the previous post I showed an example on how to use fusion APIs to get the full display name of a given assembly.

This time I am going to show a similar example. Instead of showing the full display name, we will show the display name broken up into attributes and values.

//
// EnumIdAttr.cpp
//
// Enumerate the identity attributes of a given assembly.
//

#include "fusion.h"
#include "windows.h"
#include "stdio.h"
#include "mscoree.h"
#include "isolation.h"

typedef HRESULT (__stdcall *PFNGETREF)(LPCWSTR pwzFile, REFIID riid, IUnknown **ppUnk);
typedef HRESULT (__stdcall *PFNGETAUTH)(IIdentityAuthority **ppIIdentityAuthority);

PFNGETREF g_pfnGetAssemblyIdentityFromFile = NULL;
PFNGETAUTH g_pfnGetIdentityAuthority = NULL;
IUnknown *g_pUnk = NULL;

bool Init()
{
HRESULT hr = S_OK;
DWORD dwSize = 0;
bool bRC = false;

hr = CorBindToRuntimeEx(NULL, L"wks", 0, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, (void **)&g_pUnk);
if(FAILED(hr)) {
printf("Error: Failed to initialize CLR runtime! hr = 0x%0x\n", hr);
goto Exit;
}

if (SUCCEEDED(hr)) {
hr = GetRealProcAddress("GetAssemblyIdentityFromFile", (VOID **)&g_pfnGetAssemblyIdentityFromFile);
}

    if (SUCCEEDED(hr)) {
hr = GetRealProcAddress("GetIdentityAuthority", (VOID **)&g_pfnGetIdentityAuthority);
}

    if (!g_pfnGetAssemblyIdentityFromFile || !g_pfnGetIdentityAuthority) {
printf("Error: Cannot get required APIs from fusion.dll!\n");
goto Exit;
}

    bRC = true;

Exit:
return bRC;
}

void Shutdown()
{
if(g_pUnk) {
g_pUnk->Release();
g_pUnk = NULL;
}
}

void Usage()
{
printf("EnumIdAttr: A tool to enumerate the identity attributes of a given assembly.\n\n");
printf("Usage: EnumIdAttr AsmFilePath\n");
printf("\n");
}

int _cdecl wmain(int argc, LPCWSTR argv[])
{
int iResult = 1;
IUnknown *pUnk = NULL;
IReferenceIdentity *pRef = NULL;
HRESULT hr = S_OK;
IEnumIDENTITY_ATTRIBUTE *pEnum = NULL;
BYTE abData[1024];
DWORD cbAvailable;
DWORD cbUsed;
IDENTITY_ATTRIBUTE_BLOB *pBlob;

    if(argc != 2) {
Usage();
goto Exit;
}

    if(!Init()) {
printf("Failure initializing EnumIdAttr.\n");
goto Exit;
}

    hr = g_pfnGetAssemblyIdentityFromFile(argv[1], __uuidof(IReferenceIdentity), &pUnk);
if (FAILED(hr)) {
printf("GetAssemblyIdentityFromFile failed with hr = 0x%x", hr);
goto Exit;
}

    hr = pUnk->QueryInterface(__uuidof(IReferenceIdentity), (void**)&pRef);
if (FAILED(hr)) {
goto Exit;
}

    hr = pRef->EnumAttributes(&pEnum);
if (FAILED(hr)) {
printf("IReferenceIdentity::EnumAttributes failed with hr = 0x%x", hr);
goto Exit;
}

    pBlob = (IDENTITY_ATTRIBUTE_BLOB *)(abData);
while (1) {
cbAvailable = sizeof(abData);
hr = pEnum->CurrentIntoBuffer(cbAvailable, abData, &cbUsed);
if (FAILED(hr)) {
printf("IEnumIDENTITY_ATTRIBUTE::CurrentIntoBuffer failed with hr = 0x%x", hr);
goto Exit;
}

        if (! cbUsed) {
break;
}

        LPWSTR pwzName = (LPWSTR)(abData + pBlob->ofsName);
LPWSTR pwzValue = (LPWSTR)(abData + pBlob->ofsValue);
printf("%ws = %ws\n", pwzName, pwzValue);

        hr = pEnum->Skip(1);
if (FAILED(hr)) {
printf("IEnumIDENTITY_ATTRIBUTE::Skip failed with hr = 0x%x", hr);
goto Exit;
}
}

    iResult = 0;

Exit:

    Shutdown();

    if (pUnk) {
pUnk->Release();
}

    if (pRef) {
pRef->Release();
}

    if (pEnum) {
pEnum->Release();
}

    return iResult;
}

Sample output:

D:\>enumidattr.exe d:\WINDOWS\microsoft.net\Framework\v2.0.50727\system.dll
Culture = neutral
name = System
processorArchitecture = MSIL
PublicKeyToken = b77a5c561934e089
Version = 2.0.0.0