+++ /dev/null
-/*
- * assembly parser
- *
- * 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
- */
-
-#include "fusionpriv.h"
-
-#include <wincrypt.h>
-#include <dbghelp.h>
-#include <corhdr.h>
-
-#define TableFromToken(tk) (TypeFromToken(tk) >> 24)
-#define TokenFromTable(idx) (idx << 24)
-
-#define MAX_CLR_TABLES 64
-
-#define MD_STRINGS_BIT 0x1
-#define MD_GUIDS_BIT 0x2
-#define MD_BLOBS_BIT 0x4
-
-typedef struct tagCLRTABLE
-{
- INT rows;
- DWORD offset;
-} CLRTABLE;
-
-struct tagASSEMBLY
-{
- LPWSTR path;
-
- HANDLE hfile;
- HANDLE hmap;
- BYTE *data;
-
- IMAGE_NT_HEADERS *nthdr;
- IMAGE_COR20_HEADER *corhdr;
-
- METADATAHDR *metadatahdr;
-
- METADATATABLESHDR *tableshdr;
- DWORD numtables;
- DWORD *numrows;
- CLRTABLE tables[MAX_CLR_TABLES];
-
- DWORD stringsz;
- DWORD guidsz;
- DWORD blobsz;
-
- BYTE *strings;
- BYTE *blobs;
-};
-
-static DWORD rva_to_offset(IMAGE_NT_HEADERS *nthdrs, DWORD rva)
-{
- DWORD offset = rva, limit;
- IMAGE_SECTION_HEADER *img;
- WORD i;
-
- img = IMAGE_FIRST_SECTION(nthdrs);
-
- if (rva < img->PointerToRawData)
- return rva;
-
- for (i = 0; i < nthdrs->FileHeader.NumberOfSections; i++)
- {
- if (img[i].SizeOfRawData)
- limit = img[i].SizeOfRawData;
- else
- limit = img[i].Misc.VirtualSize;
-
- if (rva >= img[i].VirtualAddress &&
- rva < (img[i].VirtualAddress + limit))
- {
- if (img[i].PointerToRawData != 0)
- {
- offset -= img[i].VirtualAddress;
- offset += img[i].PointerToRawData;
- }
-
- return offset;
- }
- }
-
- return 0;
-}
-
-static BYTE *GetData(BYTE *pData, ULONG *pLength)
-{
- if ((*pData & 0x80) == 0x00)
- {
- *pLength = (*pData & 0x7f);
- return pData + 1;
- }
-
- if ((*pData & 0xC0) == 0x80)
- {
- *pLength = ((*pData & 0x3f) << 8 | *(pData + 1));
- return pData + 2;
- }
-
- if ((*pData & 0xE0) == 0xC0)
- {
- *pLength = ((*pData & 0x1f) << 24 | *(pData + 1) << 16 |
- *(pData + 2) << 8 | *(pData + 3));
- return pData + 4;
- }
-
- *pLength = (ULONG)-1;
- return 0;
-}
-
-static VOID *assembly_data_offset(ASSEMBLY *assembly, ULONG offset)
-{
- return &assembly->data[offset];
-}
-
-#define MAX_TABLES_WORD 0xFFFF
-#define MAX_TABLES_1BIT_ENCODE 32767
-#define MAX_TABLES_2BIT_ENCODE 16383
-#define MAX_TABLES_3BIT_ENCODE 8191
-#define MAX_TABLES_5BIT_ENCODE 2047
-
-static inline ULONG get_table_size(const ASSEMBLY *assembly, DWORD index)
-{
- DWORD size;
- INT tables;
-
- switch (TokenFromTable(index))
- {
- case mdtModule:
- {
- size = sizeof(MODULETABLE) + (assembly->stringsz - sizeof(WORD)) +
- 2 * (assembly->guidsz - sizeof(WORD));
- break;
- }
- case mdtTypeRef:
- {
- size = sizeof(TYPEREFTABLE) + 2 * (assembly->stringsz - sizeof(WORD));
-
- /* ResolutionScope:ResolutionScope */
- tables = max(assembly->tables[TableFromToken(mdtModule)].rows,
- assembly->tables[TableFromToken(mdtModuleRef)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtAssemblyRef)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtTypeRef)].rows);
- size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0;
- break;
- }
- case mdtTypeDef:
- {
- size = sizeof(TYPEDEFTABLE) + 2 * (assembly->stringsz - sizeof(WORD));
-
- /* Extends:TypeDefOrRef */
- tables = max(assembly->tables[TableFromToken(mdtTypeDef)].rows,
- assembly->tables[TableFromToken(mdtTypeRef)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtTypeSpec)].rows);
- size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0;
-
- size += (assembly->tables[TableFromToken(mdtFieldDef)].rows >
- MAX_TABLES_WORD) ? sizeof(WORD) : 0;
- size += (assembly->tables[TableFromToken(mdtMethodDef)].rows >
- MAX_TABLES_WORD) ? sizeof(WORD) : 0;
- break;
- }
- case mdtFieldDef:
- {
- size = sizeof(FIELDTABLE) + (assembly->stringsz - sizeof(WORD)) +
- (assembly->blobsz - sizeof(WORD));
- break;
- }
- case mdtMethodDef:
- {
- size = sizeof(METHODDEFTABLE) + (assembly->stringsz - sizeof(WORD)) +
- (assembly->blobsz - sizeof(WORD));
-
- size += (assembly->tables[TableFromToken(mdtParamDef)].rows >
- MAX_TABLES_WORD) ? sizeof(WORD) : 0;
- break;
- }
- case mdtParamDef:
- {
- size = sizeof(PARAMTABLE) + (assembly->stringsz - sizeof(WORD));
- break;
- }
- case mdtInterfaceImpl:
- {
- size = sizeof(INTERFACEIMPLTABLE);
-
- /* Interface:TypeDefOrRef */
- tables = max(assembly->tables[TableFromToken(mdtTypeDef)].rows,
- assembly->tables[TableFromToken(mdtTypeRef)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtTypeSpec)].rows);
- size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0;
- break;
- }
- case mdtMemberRef:
- {
- size = sizeof(MEMBERREFTABLE) + (assembly->stringsz - sizeof(WORD)) +
- (assembly->blobsz - sizeof(WORD));
-
- /* Class:MemberRefParent */
- tables = max(assembly->tables[TableFromToken(mdtTypeRef)].rows,
- assembly->tables[TableFromToken(mdtModuleRef)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtMethodDef)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtTypeSpec)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtTypeDef)].rows);
- size += (tables > MAX_TABLES_3BIT_ENCODE) ? sizeof(WORD) : 0;
- break;
- }
- case 0x0B000000: /* FIXME */
- {
- size = sizeof(CONSTANTTABLE) + (assembly->blobsz - sizeof(WORD));
-
- /* Parent:HasConstant */
- tables = max(assembly->tables[TableFromToken(mdtParamDef)].rows,
- assembly->tables[TableFromToken(mdtFieldDef)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtProperty)].rows);
- size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0;
- break;
- }
- case mdtCustomAttribute:
- {
- size = sizeof(CUSTOMATTRIBUTETABLE) + (assembly->blobsz - sizeof(WORD));
-
- /* Parent:HasCustomAttribute */
- tables = max(assembly->tables[TableFromToken(mdtMethodDef)].rows,
- assembly->tables[TableFromToken(mdtFieldDef)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtTypeRef)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtTypeDef)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtParamDef)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtInterfaceImpl)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtMemberRef)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtPermission)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtProperty)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtEvent)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtSignature)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtModuleRef)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtTypeSpec)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtAssembly)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtFile)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtExportedType)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtManifestResource)].rows);
- size += (tables > MAX_TABLES_5BIT_ENCODE) ? sizeof(WORD) : 0;
-
- /* Type:CustomAttributeType */
- tables = max(assembly->tables[TableFromToken(mdtMethodDef)].rows,
- assembly->tables[TableFromToken(mdtMemberRef)].rows);
- size += (tables > MAX_TABLES_3BIT_ENCODE) ? sizeof(WORD) : 0;
- break;
- }
- case 0x0D000000: /* FIXME */
- {
- size = sizeof(FIELDMARSHALTABLE) + (assembly->blobsz - sizeof(WORD));
-
- /* Parent:HasFieldMarshal */
- tables = max(assembly->tables[TableFromToken(mdtFieldDef)].rows,
- assembly->tables[TableFromToken(mdtParamDef)].rows);
- size += (tables > MAX_TABLES_1BIT_ENCODE) ? sizeof(WORD) : 0;
- break;
- }
- case mdtPermission:
- {
- size = sizeof(DECLSECURITYTABLE) + (assembly->blobsz - sizeof(WORD));
-
- /* Parent:HasDeclSecurity */
- tables = max(assembly->tables[TableFromToken(mdtTypeDef)].rows,
- assembly->tables[TableFromToken(mdtMethodDef)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtAssembly)].rows);
- size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0;
- break;
- }
- case 0x0F000000: /* FIXME */
- {
- size = sizeof(CLASSLAYOUTTABLE);
- size += (assembly->tables[TableFromToken(mdtTypeDef)].rows >
- MAX_TABLES_WORD) ? sizeof(WORD) : 0;
- break;
- }
- case 0x10000000: /* FIXME */
- {
- size = sizeof(FIELDLAYOUTTABLE);
- size += (assembly->tables[TableFromToken(mdtFieldDef)].rows >
- MAX_TABLES_WORD) ? sizeof(WORD) : 0;
- break;
- }
- case mdtSignature:
- {
- size = sizeof(STANDALONESIGTABLE) + (assembly->blobsz - sizeof(WORD));
- break;
- }
- case 0x12000000: /* FIXME */
- {
- size = sizeof(EVENTMAPTABLE);
- size += (assembly->tables[TableFromToken(mdtTypeDef)].rows >
- MAX_TABLES_WORD) ? sizeof(WORD) : 0;
- size += (assembly->tables[TableFromToken(mdtEvent)].rows >
- MAX_TABLES_WORD) ? sizeof(WORD) : 0;
- break;
- }
- case mdtEvent:
- {
- size = sizeof(EVENTTABLE) + (assembly->stringsz - sizeof(WORD));
-
- /* EventType:TypeDefOrRef */
- tables = max(assembly->tables[TableFromToken(mdtTypeDef)].rows,
- assembly->tables[TableFromToken(mdtTypeRef)].rows);
- tables = max(tables, assembly->tables[TableFromToken(mdtTypeSpec)].rows);
- size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0;
- break;
- }
- case 0x15000000:/* FIXME */
- {
- size = sizeof(PROPERTYMAPTABLE);
- size += (assembly->tables[TableFromToken(mdtTypeDef)].rows >
- MAX_TABLES_WORD) ? sizeof(WORD) : 0;
- size += (assembly->tables[TableFromToken(mdtProperty)].rows >
- MAX_TABLES_WORD) ? sizeof(WORD) : 0;
- break;
- }
- case mdtProperty:
- {
- size = sizeof(PROPERTYTABLE) + (assembly->stringsz - sizeof(WORD)) +
- (assembly->blobsz - sizeof(WORD));
- break;
- }
- case 0x18000000: /* FIXME */
- {
- size = sizeof(METHODSEMANTICSTABLE);
-
- /* Association:HasSemantics */
- tables = max(assembly->tables[TableFromToken(mdtEvent)].rows,
- assembly->tables[TableFromToken(mdtProperty)].rows);
- size += (tables > MAX_TABLES_1BIT_ENCODE) ? sizeof(WORD) : 0;
-
- size += (assembly->tables[TableFromToken(mdtMethodDef)].rows >
- MAX_TABLES_WORD) ? sizeof(WORD) : 0;
- break;
- }
- case 0x19000000: /* FIXME */
- {
- size = sizeof(METHODIMPLTABLE);
-
- /* MethodBody:MethodDefOrRef, MethodDeclaration:MethodDefOrRef */
- tables = max(assembly->tables[TableFromToken(mdtMethodDef)].rows,
- assembly->tables[TableFromToken(mdtMemberRef)].rows);
- size += (tables > MAX_TABLES_1BIT_ENCODE) ? 2 * sizeof(WORD) : 0;
-
- size += (assembly->tables[TableFromToken(mdtTypeDef)].rows >
- MAX_TABLES_WORD) ? sizeof(WORD) : 0;
- break;
- }
- case mdtModuleRef:
- {
- size = sizeof(MODULEREFTABLE) + (assembly->stringsz - sizeof(WORD));
- break;
- }
- case mdtTypeSpec:
- {
- size = sizeof(TYPESPECTABLE) + (assembly->blobsz - sizeof(WORD));
- break;
- }
- case 0x1C000000: /* FIXME */
- {
- size = sizeof(IMPLMAPTABLE) + (assembly->stringsz - sizeof(WORD));
-
- /* MemberForwarded:MemberForwarded */
- tables = max(assembly->tables[TableFromToken(mdtFieldDef)].rows,
- assembly->tables[TableFromToken(mdtMethodDef)].rows);
- size += (tables > MAX_TABLES_1BIT_ENCODE) ? sizeof(WORD) : 0;
-
- size += (assembly->tables[TableFromToken(mdtModuleRef)].rows >
- MAX_TABLES_WORD) ? sizeof(WORD) : 0;
- break;
- }
- case 0x1D000000: /* FIXME */
- {
- size = sizeof(FIELDRVATABLE);
- size += (assembly->tables[TableFromToken(mdtFieldDef)].rows >
- MAX_TABLES_WORD) ? sizeof(WORD) : 0;
- break;
- }
- case mdtAssembly:
- {
- size = sizeof(ASSEMBLYTABLE) + 2 * (assembly->stringsz - sizeof(WORD)) +
- (assembly->blobsz - sizeof(WORD));
- break;
- }
- case 0x20000001: /* FIXME */
- {
- size = sizeof(ASSEMBLYPROCESSORTABLE);
- break;
- }
- case 0x22000000: /* FIXME */
- {
- size = sizeof(ASSEMBLYOSTABLE);
- break;
- }
- case mdtAssemblyRef:
- {
- size = sizeof(ASSEMBLYREFTABLE) + 2 * (assembly->stringsz - sizeof(WORD)) +
- 2 * (assembly->blobsz - sizeof(WORD));
- break;
- }
- case 0x24000000: /* FIXME */
- {
- size = sizeof(ASSEMBLYREFPROCESSORTABLE);
- size += (assembly->tables[TableFromToken(mdtAssemblyRef)].rows >
- MAX_TABLES_WORD) ? sizeof(WORD) : 0;
- break;
- }
- case 0x25000000: /* FIXME */
- {
- size = sizeof(ASSEMBLYREFOSTABLE);
- size += (assembly->tables[TableFromToken(mdtAssemblyRef)].rows >
- MAX_TABLES_WORD) ? sizeof(WORD) : 0;
- break;
- }
- case mdtFile:
- {
- size = sizeof(FILETABLE) + (assembly->stringsz - sizeof(WORD)) +
- (assembly->blobsz - sizeof(WORD));
- break;
- }
- case mdtExportedType:
- {
- size = sizeof(EXPORTEDTYPETABLE) + 2 * (assembly->stringsz - sizeof(WORD));
-
- /* Implementation:Implementation */
- tables = max(assembly->tables[TableFromToken(mdtFile)].rows,
- assembly->tables[TableFromToken(mdtMethodDef)].rows);
- size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0;
- break;
- }
- case mdtManifestResource:
- {
- size = sizeof(MANIFESTRESTABLE) + (assembly->stringsz - sizeof(WORD));
-
- /* Implementation:Implementation */
- tables = max(assembly->tables[TableFromToken(mdtFile)].rows,
- assembly->tables[TableFromToken(mdtAssemblyRef)].rows);
- size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0;
- break;
- }
- case 0x29000000: /* FIXME */
- {
- size = sizeof(NESTEDCLASSTABLE);
- size += (assembly->tables[TableFromToken(mdtTypeDef)].rows >
- MAX_TABLES_WORD) ? 2 * sizeof(WORD) : 0;
- break;
- }
- default:
- return 0;
- }
-
- return size;
-}
-
-static HRESULT parse_clr_tables(ASSEMBLY *assembly, ULONG offset)
-{
- DWORD i, count;
- ULONG currofs;
- ULONGLONG mask;
-
- currofs = offset;
- assembly->tableshdr = assembly_data_offset(assembly, currofs);
- if (!assembly->tableshdr)
- return E_FAIL;
-
- assembly->stringsz = (assembly->tableshdr->HeapOffsetSizes & MD_STRINGS_BIT) ?
- sizeof(DWORD) : sizeof(WORD);
- assembly->guidsz = (assembly->tableshdr->HeapOffsetSizes & MD_GUIDS_BIT) ?
- sizeof(DWORD) : sizeof(WORD);
- assembly->blobsz = (assembly->tableshdr->HeapOffsetSizes & MD_BLOBS_BIT) ?
- sizeof(DWORD) : sizeof(WORD);
-
- currofs += sizeof(METADATATABLESHDR);
- assembly->numrows = assembly_data_offset(assembly, currofs);
- if (!assembly->numrows)
- return E_FAIL;
-
- memset(assembly->tables, -1, MAX_CLR_TABLES * sizeof(CLRTABLE));
-
- for (i = count = 0, mask = 1; i < MAX_CLR_TABLES; i++, mask <<= 1)
- {
- if (assembly->tableshdr->MaskValid.QuadPart & mask)
- assembly->tables[i].rows = assembly->numrows[count++];
- }
- assembly->numtables = count;
- currofs += assembly->numtables * sizeof(DWORD);
-
- for (i = 0, mask = 1; i < MAX_CLR_TABLES; i++, mask <<= 1)
- {
- if (assembly->tableshdr->MaskValid.QuadPart & mask)
- {
- assembly->tables[i].offset = currofs;
- currofs += get_table_size(assembly, i) * assembly->tables[i].rows;
- }
- }
-
- return S_OK;
-}
-
-static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz)
-{
- METADATAHDR *metadatahdr;
- BYTE *ptr, *dest;
- DWORD size, ofs;
- ULONG rva;
-
- rva = assembly->corhdr->MetaData.VirtualAddress;
- ptr = ImageRvaToVa(assembly->nthdr, assembly->data, rva, NULL);
- if (!ptr)
- return E_FAIL;
-
- metadatahdr = (METADATAHDR *)ptr;
-
- assembly->metadatahdr = HeapAlloc(GetProcessHeap(), 0, sizeof(METADATAHDR));
- if (!assembly->metadatahdr)
- return E_OUTOFMEMORY;
-
- size = FIELD_OFFSET(METADATAHDR, Version);
- memcpy(assembly->metadatahdr, metadatahdr, size);
-
- assembly->metadatahdr->Version = (LPSTR)&metadatahdr->Version;
-
- ofs = FIELD_OFFSET(METADATAHDR, Flags);
- ptr += FIELD_OFFSET(METADATAHDR, Version) + metadatahdr->VersionLength + 1;
- dest = (BYTE *)assembly->metadatahdr + ofs;
- memcpy(dest, ptr, sizeof(METADATAHDR) - ofs);
-
- *hdrsz = sizeof(METADATAHDR) - sizeof(LPSTR) + metadatahdr->VersionLength + 1;
-
- return S_OK;
-}
-
-static HRESULT parse_clr_metadata(ASSEMBLY *assembly)
-{
- METADATASTREAMHDR *streamhdr;
- ULONG rva, i, ofs;
- LPSTR stream;
- HRESULT hr;
- DWORD hdrsz;
- BYTE *ptr;
-
- hr = parse_metadata_header(assembly, &hdrsz);
- if (FAILED(hr))
- return hr;
-
- rva = assembly->corhdr->MetaData.VirtualAddress;
- ptr = ImageRvaToVa(assembly->nthdr, assembly->data, rva + hdrsz, NULL);
- if (!ptr)
- return E_FAIL;
-
- for (i = 0; i < assembly->metadatahdr->Streams; i++)
- {
- streamhdr = (METADATASTREAMHDR *)ptr;
- ofs = rva_to_offset(assembly->nthdr, rva + streamhdr->Offset);
-
- ptr += sizeof(METADATASTREAMHDR);
- stream = (LPSTR)ptr;
-
- if (!lstrcmpA(stream, "#~"))
- {
- hr = parse_clr_tables(assembly, ofs);
- if (FAILED(hr))
- return hr;
- }
- else if (!lstrcmpA(stream, "#Strings") || !lstrcmpA(stream, "Strings"))
- assembly->strings = assembly_data_offset(assembly, ofs);
- else if (!lstrcmpA(stream, "#Blob") || !lstrcmpA(stream, "Blob"))
- assembly->blobs = assembly_data_offset(assembly, ofs);
-
- ptr += ((lstrlenA(stream) + 1) + 3) & ~3; /* align on DWORD boundary */
- }
-
- return S_OK;
-}
-
-static HRESULT parse_pe_header(ASSEMBLY *assembly)
-{
- IMAGE_DATA_DIRECTORY *datadirs;
-
- assembly->nthdr = ImageNtHeader(assembly->data);
- if (!assembly->nthdr)
- return E_FAIL;
-
- if (assembly->nthdr->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
- {
- IMAGE_OPTIONAL_HEADER64 *opthdr =
- (IMAGE_OPTIONAL_HEADER64 *)&assembly->nthdr->OptionalHeader;
- datadirs = opthdr->DataDirectory;
- }
- else
- {
- IMAGE_OPTIONAL_HEADER32 *opthdr =
- (IMAGE_OPTIONAL_HEADER32 *)&assembly->nthdr->OptionalHeader;
- datadirs = opthdr->DataDirectory;
- }
-
- if (!datadirs)
- return E_FAIL;
-
- if (!datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress ||
- !datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size)
- {
- return E_FAIL;
- }
-
- assembly->corhdr = ImageRvaToVa(assembly->nthdr, assembly->data,
- datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress, NULL);
- if (!assembly->corhdr)
- return E_FAIL;
-
- return S_OK;
-}
-
-HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
-{
- ASSEMBLY *assembly;
- HRESULT hr;
-
- *out = NULL;
-
- assembly = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ASSEMBLY));
- if (!assembly)
- return E_OUTOFMEMORY;
-
- assembly->path = strdupW(file);
- if (!assembly->path)
- {
- hr = E_OUTOFMEMORY;
- goto failed;
- }
-
- assembly->hfile = CreateFileW(file, GENERIC_READ, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (assembly->hfile == INVALID_HANDLE_VALUE)
- {
- hr = HRESULT_FROM_WIN32(GetLastError());
- goto failed;
- }
-
- assembly->hmap = CreateFileMappingW(assembly->hfile, NULL, PAGE_READONLY,
- 0, 0, NULL);
- if (!assembly->hmap)
- {
- hr = HRESULT_FROM_WIN32(GetLastError());
- goto failed;
- }
-
- assembly->data = MapViewOfFile(assembly->hmap, FILE_MAP_READ, 0, 0, 0);
- if (!assembly->data)
- {
- hr = HRESULT_FROM_WIN32(GetLastError());
- goto failed;
- }
-
- hr = parse_pe_header(assembly);
- if (FAILED(hr)) goto failed;
-
- hr = parse_clr_metadata(assembly);
- if (FAILED(hr)) goto failed;
-
- *out = assembly;
- return S_OK;
-
-failed:
- assembly_release(assembly);
- return hr;
-}
-
-HRESULT assembly_release(ASSEMBLY *assembly)
-{
- if (!assembly)
- return S_OK;
-
- HeapFree(GetProcessHeap(), 0, assembly->metadatahdr);
- HeapFree(GetProcessHeap(), 0, assembly->path);
- UnmapViewOfFile(assembly->data);
- CloseHandle(assembly->hmap);
- CloseHandle(assembly->hfile);
- HeapFree(GetProcessHeap(), 0, assembly);
-
- return S_OK;
-}
-
-static LPWSTR assembly_dup_str(const ASSEMBLY *assembly, DWORD index)
-{
- int len;
- LPWSTR cpy;
- LPCSTR str = (LPCSTR)&assembly->strings[index];
-
- len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
-
- if ((cpy = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))))
- MultiByteToWideChar(CP_ACP, 0, str, -1, cpy, len);
-
- return cpy;
-}
-
-HRESULT assembly_get_name(ASSEMBLY *assembly, LPWSTR *name)
-{
- BYTE *ptr;
- LONG offset;
- DWORD stridx;
-
- offset = assembly->tables[TableFromToken(mdtAssembly)].offset;
- if (offset == -1)
- return E_FAIL;
-
- ptr = assembly_data_offset(assembly, offset);
- if (!ptr)
- return E_FAIL;
-
- ptr += FIELD_OFFSET(ASSEMBLYTABLE, PublicKey) + assembly->blobsz;
- if (assembly->stringsz == sizeof(DWORD))
- stridx = *(DWORD *)ptr;
- else
- stridx = *(WORD *)ptr;
-
- *name = assembly_dup_str(assembly, stridx);
- if (!*name)
- return E_OUTOFMEMORY;
-
- return S_OK;
-}
-
-HRESULT assembly_get_path(const ASSEMBLY *assembly, LPWSTR *path)
-{
- LPWSTR cpy = HeapAlloc(GetProcessHeap(), 0, (strlenW(assembly->path) + 1) * sizeof(WCHAR));
- *path = cpy;
- if (cpy)
- strcpyW(cpy, assembly->path);
- else
- return E_OUTOFMEMORY;
-
- return S_OK;
-}
-
-HRESULT assembly_get_version(ASSEMBLY *assembly, LPWSTR *version)
-{
- static const WCHAR format[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
-
- ASSEMBLYTABLE *asmtbl;
- LONG offset;
-
- *version = NULL;
-
- offset = assembly->tables[TableFromToken(mdtAssembly)].offset;
- if (offset == -1)
- return E_FAIL;
-
- asmtbl = assembly_data_offset(assembly, offset);
- if (!asmtbl)
- return E_FAIL;
-
- *version = HeapAlloc(GetProcessHeap(), 0, sizeof(format) + 4 * strlen("65535") * sizeof(WCHAR));
- if (!*version)
- return E_OUTOFMEMORY;
-
- sprintfW(*version, format, asmtbl->MajorVersion, asmtbl->MinorVersion,
- asmtbl->BuildNumber, asmtbl->RevisionNumber);
-
- return S_OK;
-}
-
-PEKIND assembly_get_architecture(ASSEMBLY *assembly)
-{
- if ((assembly->corhdr->MajorRuntimeVersion == 2) && (assembly->corhdr->MinorRuntimeVersion == 0))
- return peNone; /* .NET 1.x assembly */
-
- if (assembly->nthdr->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
- return peAMD64; /* AMD64/IA64 assembly */
-
- if ((assembly->corhdr->Flags & COMIMAGE_FLAGS_ILONLY) && !(assembly->corhdr->Flags & COMIMAGE_FLAGS_32BITREQUIRED))
- return peMSIL; /* MSIL assembly */
-
- return peI386; /* x86 assembly */
-}
-
-static BYTE *assembly_get_blob(ASSEMBLY *assembly, DWORD index, ULONG *size)
-{
- return GetData(&assembly->blobs[index], size);
-}
-
-HRESULT assembly_get_pubkey_token(ASSEMBLY *assembly, LPWSTR *token)
-{
- ULONG i, size;
- LONG offset;
- BYTE *hashdata, *pubkey, *ptr;
- HCRYPTPROV crypt;
- HCRYPTHASH hash;
- BYTE tokbytes[BYTES_PER_TOKEN];
- HRESULT hr = E_FAIL;
- LPWSTR tok;
- DWORD idx;
-
- *token = NULL;
-
- offset = assembly->tables[TableFromToken(mdtAssembly)].offset;
- if (offset == -1)
- return E_FAIL;
-
- ptr = assembly_data_offset(assembly, offset);
- if (!ptr)
- return E_FAIL;
-
- ptr += FIELD_OFFSET(ASSEMBLYTABLE, PublicKey);
- if (assembly->blobsz == sizeof(DWORD))
- idx = *(DWORD *)ptr;
- else
- idx = *(WORD *)ptr;
-
- pubkey = assembly_get_blob(assembly, idx, &size);
-
- if (!CryptAcquireContextA(&crypt, NULL, NULL, PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT))
- return E_FAIL;
-
- if (!CryptCreateHash(crypt, CALG_SHA1, 0, 0, &hash))
- return E_FAIL;
-
- if (!CryptHashData(hash, pubkey, size, 0))
- return E_FAIL;
-
- size = 0;
- if (!CryptGetHashParam(hash, HP_HASHVAL, NULL, &size, 0))
- return E_FAIL;
-
- hashdata = HeapAlloc(GetProcessHeap(), 0, size);
- if (!hashdata)
- {
- hr = E_OUTOFMEMORY;
- goto done;
- }
-
- if (!CryptGetHashParam(hash, HP_HASHVAL, hashdata, &size, 0))
- goto done;
-
- for (i = size - 1; i >= size - 8; i--)
- tokbytes[size - i - 1] = hashdata[i];
-
- tok = HeapAlloc(GetProcessHeap(), 0, (TOKEN_LENGTH + 1) * sizeof(WCHAR));
- if (!tok)
- {
- hr = E_OUTOFMEMORY;
- goto done;
- }
-
- token_to_str(tokbytes, tok);
-
- *token = tok;
- hr = S_OK;
-
-done:
- HeapFree(GetProcessHeap(), 0, hashdata);
- CryptDestroyHash(hash);
- CryptReleaseContext(crypt, 0);
-
- return hr;
-}
-
-HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version)
-{
- *version = assembly->metadatahdr->Version;
- return S_OK;
-}
-
-HRESULT assembly_get_external_files(ASSEMBLY *assembly, LPWSTR **files, DWORD *count)
-{
- LONG offset;
- INT i, num_rows;
- WCHAR **ret;
- BYTE *ptr;
- DWORD idx;
-
- *count = 0;
-
- offset = assembly->tables[TableFromToken(mdtFile)].offset;
- if (offset == -1)
- return S_OK;
-
- ptr = assembly_data_offset(assembly, offset);
- if (!ptr)
- return S_OK;
-
- num_rows = assembly->tables[TableFromToken(mdtFile)].rows;
- if (num_rows <= 0)
- return S_OK;
-
- ret = HeapAlloc(GetProcessHeap(), 0, num_rows * sizeof(WCHAR *));
- if (!ret)
- return E_OUTOFMEMORY;
-
- for (i = 0; i < num_rows; i++)
- {
- ptr += sizeof(DWORD); /* skip Flags field */
- if (assembly->stringsz == sizeof(DWORD))
- idx = *(DWORD *)ptr;
- else
- idx = *(WORD *)ptr;
-
- ret[i] = assembly_dup_str(assembly, idx);
- if (!ret[i])
- {
- for (; i >= 0; i--) HeapFree(GetProcessHeap(), 0, ret[i]);
- HeapFree(GetProcessHeap(), 0, ret);
- return E_OUTOFMEMORY;
- }
- ptr += assembly->stringsz; /* skip Name field */
- ptr += assembly->blobsz; /* skip Hash field */
- }
- *count = num_rows;
- *files = ret;
- return S_OK;
-}