4 * Copyright 2008 James Hawkins
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "fusionpriv.h"
27 #define TableFromToken(tk) (TypeFromToken(tk) >> 24)
28 #define TokenFromTable(idx) (idx << 24)
30 #define MAX_CLR_TABLES 64
32 #define MD_STRINGS_BIT 0x1
33 #define MD_GUIDS_BIT 0x2
34 #define MD_BLOBS_BIT 0x4
36 typedef struct tagCLRTABLE
50 IMAGE_NT_HEADERS
*nthdr
;
51 IMAGE_COR20_HEADER
*corhdr
;
53 METADATAHDR
*metadatahdr
;
55 METADATATABLESHDR
*tableshdr
;
58 CLRTABLE tables
[MAX_CLR_TABLES
];
68 static DWORD
rva_to_offset(IMAGE_NT_HEADERS
*nthdrs
, DWORD rva
)
70 DWORD offset
= rva
, limit
;
71 IMAGE_SECTION_HEADER
*img
;
74 img
= IMAGE_FIRST_SECTION(nthdrs
);
76 if (rva
< img
->PointerToRawData
)
79 for (i
= 0; i
< nthdrs
->FileHeader
.NumberOfSections
; i
++)
81 if (img
[i
].SizeOfRawData
)
82 limit
= img
[i
].SizeOfRawData
;
84 limit
= img
[i
].Misc
.VirtualSize
;
86 if (rva
>= img
[i
].VirtualAddress
&&
87 rva
< (img
[i
].VirtualAddress
+ limit
))
89 if (img
[i
].PointerToRawData
!= 0)
91 offset
-= img
[i
].VirtualAddress
;
92 offset
+= img
[i
].PointerToRawData
;
102 static BYTE
*GetData(BYTE
*pData
, ULONG
*pLength
)
104 if ((*pData
& 0x80) == 0x00)
106 *pLength
= (*pData
& 0x7f);
110 if ((*pData
& 0xC0) == 0x80)
112 *pLength
= ((*pData
& 0x3f) << 8 | *(pData
+ 1));
116 if ((*pData
& 0xE0) == 0xC0)
118 *pLength
= ((*pData
& 0x1f) << 24 | *(pData
+ 1) << 16 |
119 *(pData
+ 2) << 8 | *(pData
+ 3));
123 *pLength
= (ULONG
)-1;
127 static VOID
*assembly_data_offset(ASSEMBLY
*assembly
, ULONG offset
)
129 return &assembly
->data
[offset
];
132 #define MAX_TABLES_WORD 0xFFFF
133 #define MAX_TABLES_1BIT_ENCODE 32767
134 #define MAX_TABLES_2BIT_ENCODE 16383
135 #define MAX_TABLES_3BIT_ENCODE 8191
136 #define MAX_TABLES_5BIT_ENCODE 2047
138 static inline ULONG
get_table_size(const ASSEMBLY
*assembly
, DWORD index
)
143 switch (TokenFromTable(index
))
147 size
= sizeof(MODULETABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
148 2 * (assembly
->guidsz
- sizeof(WORD
));
153 size
= sizeof(TYPEREFTABLE
) + 2 * (assembly
->stringsz
- sizeof(WORD
));
155 /* ResolutionScope:ResolutionScope */
156 tables
= max(assembly
->tables
[TableFromToken(mdtModule
)].rows
,
157 assembly
->tables
[TableFromToken(mdtModuleRef
)].rows
);
158 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtAssemblyRef
)].rows
);
159 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
);
160 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
165 size
= sizeof(TYPEDEFTABLE
) + 2 * (assembly
->stringsz
- sizeof(WORD
));
167 /* Extends:TypeDefOrRef */
168 tables
= max(assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
,
169 assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
);
170 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeSpec
)].rows
);
171 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
173 size
+= (assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
>
174 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
175 size
+= (assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
>
176 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
181 size
= sizeof(FIELDTABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
182 (assembly
->blobsz
- sizeof(WORD
));
187 size
= sizeof(METHODDEFTABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
188 (assembly
->blobsz
- sizeof(WORD
));
190 size
+= (assembly
->tables
[TableFromToken(mdtParamDef
)].rows
>
191 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
196 size
= sizeof(PARAMTABLE
) + (assembly
->stringsz
- sizeof(WORD
));
199 case mdtInterfaceImpl
:
201 size
= sizeof(INTERFACEIMPLTABLE
);
203 /* Interface:TypeDefOrRef */
204 tables
= max(assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
,
205 assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
);
206 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeSpec
)].rows
);
207 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
212 size
= sizeof(MEMBERREFTABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
213 (assembly
->blobsz
- sizeof(WORD
));
215 /* Class:MemberRefParent */
216 tables
= max(assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
,
217 assembly
->tables
[TableFromToken(mdtModuleRef
)].rows
);
218 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
);
219 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeSpec
)].rows
);
220 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
);
221 size
+= (tables
> MAX_TABLES_3BIT_ENCODE
) ? sizeof(WORD
) : 0;
224 case 0x0B000000: /* FIXME */
226 size
= sizeof(CONSTANTTABLE
) + (assembly
->blobsz
- sizeof(WORD
));
228 /* Parent:HasConstant */
229 tables
= max(assembly
->tables
[TableFromToken(mdtParamDef
)].rows
,
230 assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
);
231 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtProperty
)].rows
);
232 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
235 case mdtCustomAttribute
:
237 size
= sizeof(CUSTOMATTRIBUTETABLE
) + (assembly
->blobsz
- sizeof(WORD
));
239 /* Parent:HasCustomAttribute */
240 tables
= max(assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
,
241 assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
);
242 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
);
243 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
);
244 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtParamDef
)].rows
);
245 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtInterfaceImpl
)].rows
);
246 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtMemberRef
)].rows
);
247 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtPermission
)].rows
);
248 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtProperty
)].rows
);
249 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtEvent
)].rows
);
250 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtSignature
)].rows
);
251 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtModuleRef
)].rows
);
252 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeSpec
)].rows
);
253 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtAssembly
)].rows
);
254 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtFile
)].rows
);
255 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtExportedType
)].rows
);
256 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtManifestResource
)].rows
);
257 size
+= (tables
> MAX_TABLES_5BIT_ENCODE
) ? sizeof(WORD
) : 0;
259 /* Type:CustomAttributeType */
260 tables
= max(assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
,
261 assembly
->tables
[TableFromToken(mdtMemberRef
)].rows
);
262 size
+= (tables
> MAX_TABLES_3BIT_ENCODE
) ? sizeof(WORD
) : 0;
265 case 0x0D000000: /* FIXME */
267 size
= sizeof(FIELDMARSHALTABLE
) + (assembly
->blobsz
- sizeof(WORD
));
269 /* Parent:HasFieldMarshal */
270 tables
= max(assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
,
271 assembly
->tables
[TableFromToken(mdtParamDef
)].rows
);
272 size
+= (tables
> MAX_TABLES_1BIT_ENCODE
) ? sizeof(WORD
) : 0;
277 size
= sizeof(DECLSECURITYTABLE
) + (assembly
->blobsz
- sizeof(WORD
));
279 /* Parent:HasDeclSecurity */
280 tables
= max(assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
,
281 assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
);
282 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtAssembly
)].rows
);
283 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
286 case 0x0F000000: /* FIXME */
288 size
= sizeof(CLASSLAYOUTTABLE
);
289 size
+= (assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
>
290 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
293 case 0x10000000: /* FIXME */
295 size
= sizeof(FIELDLAYOUTTABLE
);
296 size
+= (assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
>
297 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
302 size
= sizeof(STANDALONESIGTABLE
) + (assembly
->blobsz
- sizeof(WORD
));
305 case 0x12000000: /* FIXME */
307 size
= sizeof(EVENTMAPTABLE
);
308 size
+= (assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
>
309 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
310 size
+= (assembly
->tables
[TableFromToken(mdtEvent
)].rows
>
311 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
316 size
= sizeof(EVENTTABLE
) + (assembly
->stringsz
- sizeof(WORD
));
318 /* EventType:TypeDefOrRef */
319 tables
= max(assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
,
320 assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
);
321 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeSpec
)].rows
);
322 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
325 case 0x15000000:/* FIXME */
327 size
= sizeof(PROPERTYMAPTABLE
);
328 size
+= (assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
>
329 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
330 size
+= (assembly
->tables
[TableFromToken(mdtProperty
)].rows
>
331 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
336 size
= sizeof(PROPERTYTABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
337 (assembly
->blobsz
- sizeof(WORD
));
340 case 0x18000000: /* FIXME */
342 size
= sizeof(METHODSEMANTICSTABLE
);
344 /* Association:HasSemantics */
345 tables
= max(assembly
->tables
[TableFromToken(mdtEvent
)].rows
,
346 assembly
->tables
[TableFromToken(mdtProperty
)].rows
);
347 size
+= (tables
> MAX_TABLES_1BIT_ENCODE
) ? sizeof(WORD
) : 0;
349 size
+= (assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
>
350 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
353 case 0x19000000: /* FIXME */
355 size
= sizeof(METHODIMPLTABLE
);
357 /* MethodBody:MethodDefOrRef, MethodDeclaration:MethodDefOrRef */
358 tables
= max(assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
,
359 assembly
->tables
[TableFromToken(mdtMemberRef
)].rows
);
360 size
+= (tables
> MAX_TABLES_1BIT_ENCODE
) ? 2 * sizeof(WORD
) : 0;
362 size
+= (assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
>
363 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
368 size
= sizeof(MODULEREFTABLE
) + (assembly
->stringsz
- sizeof(WORD
));
373 size
= sizeof(TYPESPECTABLE
) + (assembly
->blobsz
- sizeof(WORD
));
376 case 0x1C000000: /* FIXME */
378 size
= sizeof(IMPLMAPTABLE
) + (assembly
->stringsz
- sizeof(WORD
));
380 /* MemberForwarded:MemberForwarded */
381 tables
= max(assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
,
382 assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
);
383 size
+= (tables
> MAX_TABLES_1BIT_ENCODE
) ? sizeof(WORD
) : 0;
385 size
+= (assembly
->tables
[TableFromToken(mdtModuleRef
)].rows
>
386 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
389 case 0x1D000000: /* FIXME */
391 size
= sizeof(FIELDRVATABLE
);
392 size
+= (assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
>
393 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
398 size
= sizeof(ASSEMBLYTABLE
) + 2 * (assembly
->stringsz
- sizeof(WORD
)) +
399 (assembly
->blobsz
- sizeof(WORD
));
402 case 0x20000001: /* FIXME */
404 size
= sizeof(ASSEMBLYPROCESSORTABLE
);
407 case 0x22000000: /* FIXME */
409 size
= sizeof(ASSEMBLYOSTABLE
);
414 size
= sizeof(ASSEMBLYREFTABLE
) + 2 * (assembly
->stringsz
- sizeof(WORD
)) +
415 2 * (assembly
->blobsz
- sizeof(WORD
));
418 case 0x24000000: /* FIXME */
420 size
= sizeof(ASSEMBLYREFPROCESSORTABLE
);
421 size
+= (assembly
->tables
[TableFromToken(mdtAssemblyRef
)].rows
>
422 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
425 case 0x25000000: /* FIXME */
427 size
= sizeof(ASSEMBLYREFOSTABLE
);
428 size
+= (assembly
->tables
[TableFromToken(mdtAssemblyRef
)].rows
>
429 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
434 size
= sizeof(FILETABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
435 (assembly
->blobsz
- sizeof(WORD
));
438 case mdtExportedType
:
440 size
= sizeof(EXPORTEDTYPETABLE
) + 2 * (assembly
->stringsz
- sizeof(WORD
));
442 /* Implementation:Implementation */
443 tables
= max(assembly
->tables
[TableFromToken(mdtFile
)].rows
,
444 assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
);
445 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
448 case mdtManifestResource
:
450 size
= sizeof(MANIFESTRESTABLE
) + (assembly
->stringsz
- sizeof(WORD
));
452 /* Implementation:Implementation */
453 tables
= max(assembly
->tables
[TableFromToken(mdtFile
)].rows
,
454 assembly
->tables
[TableFromToken(mdtAssemblyRef
)].rows
);
455 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
458 case 0x29000000: /* FIXME */
460 size
= sizeof(NESTEDCLASSTABLE
);
461 size
+= (assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
>
462 MAX_TABLES_WORD
) ? 2 * sizeof(WORD
) : 0;
472 static HRESULT
parse_clr_tables(ASSEMBLY
*assembly
, ULONG offset
)
479 assembly
->tableshdr
= assembly_data_offset(assembly
, currofs
);
480 if (!assembly
->tableshdr
)
483 assembly
->stringsz
= (assembly
->tableshdr
->HeapOffsetSizes
& MD_STRINGS_BIT
) ?
484 sizeof(DWORD
) : sizeof(WORD
);
485 assembly
->guidsz
= (assembly
->tableshdr
->HeapOffsetSizes
& MD_GUIDS_BIT
) ?
486 sizeof(DWORD
) : sizeof(WORD
);
487 assembly
->blobsz
= (assembly
->tableshdr
->HeapOffsetSizes
& MD_BLOBS_BIT
) ?
488 sizeof(DWORD
) : sizeof(WORD
);
490 currofs
+= sizeof(METADATATABLESHDR
);
491 assembly
->numrows
= assembly_data_offset(assembly
, currofs
);
492 if (!assembly
->numrows
)
495 memset(assembly
->tables
, -1, MAX_CLR_TABLES
* sizeof(CLRTABLE
));
497 for (i
= count
= 0, mask
= 1; i
< MAX_CLR_TABLES
; i
++, mask
<<= 1)
499 if (assembly
->tableshdr
->MaskValid
.QuadPart
& mask
)
500 assembly
->tables
[i
].rows
= assembly
->numrows
[count
++];
502 assembly
->numtables
= count
;
503 currofs
+= assembly
->numtables
* sizeof(DWORD
);
505 for (i
= 0, mask
= 1; i
< MAX_CLR_TABLES
; i
++, mask
<<= 1)
507 if (assembly
->tableshdr
->MaskValid
.QuadPart
& mask
)
509 assembly
->tables
[i
].offset
= currofs
;
510 currofs
+= get_table_size(assembly
, i
) * assembly
->tables
[i
].rows
;
517 static HRESULT
parse_metadata_header(ASSEMBLY
*assembly
, DWORD
*hdrsz
)
519 METADATAHDR
*metadatahdr
;
524 rva
= assembly
->corhdr
->MetaData
.VirtualAddress
;
525 ptr
= ImageRvaToVa(assembly
->nthdr
, assembly
->data
, rva
, NULL
);
529 metadatahdr
= (METADATAHDR
*)ptr
;
531 assembly
->metadatahdr
= HeapAlloc(GetProcessHeap(), 0, sizeof(METADATAHDR
));
532 if (!assembly
->metadatahdr
)
533 return E_OUTOFMEMORY
;
535 size
= FIELD_OFFSET(METADATAHDR
, Version
);
536 memcpy(assembly
->metadatahdr
, metadatahdr
, size
);
538 assembly
->metadatahdr
->Version
= (LPSTR
)&metadatahdr
->Version
;
540 ofs
= FIELD_OFFSET(METADATAHDR
, Flags
);
541 ptr
+= FIELD_OFFSET(METADATAHDR
, Version
) + metadatahdr
->VersionLength
+ 1;
542 dest
= (BYTE
*)assembly
->metadatahdr
+ ofs
;
543 memcpy(dest
, ptr
, sizeof(METADATAHDR
) - ofs
);
545 *hdrsz
= sizeof(METADATAHDR
) - sizeof(LPSTR
) + metadatahdr
->VersionLength
+ 1;
550 static HRESULT
parse_clr_metadata(ASSEMBLY
*assembly
)
552 METADATASTREAMHDR
*streamhdr
;
559 hr
= parse_metadata_header(assembly
, &hdrsz
);
563 rva
= assembly
->corhdr
->MetaData
.VirtualAddress
;
564 ptr
= ImageRvaToVa(assembly
->nthdr
, assembly
->data
, rva
+ hdrsz
, NULL
);
568 for (i
= 0; i
< assembly
->metadatahdr
->Streams
; i
++)
570 streamhdr
= (METADATASTREAMHDR
*)ptr
;
571 ofs
= rva_to_offset(assembly
->nthdr
, rva
+ streamhdr
->Offset
);
573 ptr
+= sizeof(METADATASTREAMHDR
);
576 if (!lstrcmpA(stream
, "#~"))
578 hr
= parse_clr_tables(assembly
, ofs
);
582 else if (!lstrcmpA(stream
, "#Strings") || !lstrcmpA(stream
, "Strings"))
583 assembly
->strings
= assembly_data_offset(assembly
, ofs
);
584 else if (!lstrcmpA(stream
, "#Blob") || !lstrcmpA(stream
, "Blob"))
585 assembly
->blobs
= assembly_data_offset(assembly
, ofs
);
587 ptr
+= ((lstrlenA(stream
) + 1) + 3) & ~3; /* align on DWORD boundary */
593 static HRESULT
parse_pe_header(ASSEMBLY
*assembly
)
595 IMAGE_DATA_DIRECTORY
*datadirs
;
597 assembly
->nthdr
= ImageNtHeader(assembly
->data
);
598 if (!assembly
->nthdr
)
601 if (assembly
->nthdr
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR64_MAGIC
)
603 IMAGE_OPTIONAL_HEADER64
*opthdr
=
604 (IMAGE_OPTIONAL_HEADER64
*)&assembly
->nthdr
->OptionalHeader
;
605 datadirs
= opthdr
->DataDirectory
;
609 IMAGE_OPTIONAL_HEADER32
*opthdr
=
610 (IMAGE_OPTIONAL_HEADER32
*)&assembly
->nthdr
->OptionalHeader
;
611 datadirs
= opthdr
->DataDirectory
;
617 if (!datadirs
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
||
618 !datadirs
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
)
623 assembly
->corhdr
= ImageRvaToVa(assembly
->nthdr
, assembly
->data
,
624 datadirs
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
, NULL
);
625 if (!assembly
->corhdr
)
631 HRESULT
assembly_create(ASSEMBLY
**out
, LPCWSTR file
)
638 assembly
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ASSEMBLY
));
640 return E_OUTOFMEMORY
;
642 assembly
->path
= strdupW(file
);
649 assembly
->hfile
= CreateFileW(file
, GENERIC_READ
, FILE_SHARE_READ
,
650 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
651 if (assembly
->hfile
== INVALID_HANDLE_VALUE
)
653 hr
= HRESULT_FROM_WIN32(GetLastError());
657 assembly
->hmap
= CreateFileMappingW(assembly
->hfile
, NULL
, PAGE_READONLY
,
661 hr
= HRESULT_FROM_WIN32(GetLastError());
665 assembly
->data
= MapViewOfFile(assembly
->hmap
, FILE_MAP_READ
, 0, 0, 0);
668 hr
= HRESULT_FROM_WIN32(GetLastError());
672 hr
= parse_pe_header(assembly
);
673 if (FAILED(hr
)) goto failed
;
675 hr
= parse_clr_metadata(assembly
);
676 if (FAILED(hr
)) goto failed
;
682 assembly_release(assembly
);
686 HRESULT
assembly_release(ASSEMBLY
*assembly
)
691 HeapFree(GetProcessHeap(), 0, assembly
->metadatahdr
);
692 HeapFree(GetProcessHeap(), 0, assembly
->path
);
693 UnmapViewOfFile(assembly
->data
);
694 CloseHandle(assembly
->hmap
);
695 CloseHandle(assembly
->hfile
);
696 HeapFree(GetProcessHeap(), 0, assembly
);
701 static LPWSTR
assembly_dup_str(const ASSEMBLY
*assembly
, DWORD index
)
705 LPCSTR str
= (LPCSTR
)&assembly
->strings
[index
];
707 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
709 if ((cpy
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))))
710 MultiByteToWideChar(CP_ACP
, 0, str
, -1, cpy
, len
);
715 HRESULT
assembly_get_name(ASSEMBLY
*assembly
, LPWSTR
*name
)
721 offset
= assembly
->tables
[TableFromToken(mdtAssembly
)].offset
;
725 ptr
= assembly_data_offset(assembly
, offset
);
729 ptr
+= FIELD_OFFSET(ASSEMBLYTABLE
, PublicKey
) + assembly
->blobsz
;
730 if (assembly
->stringsz
== sizeof(DWORD
))
731 stridx
= *(DWORD
*)ptr
;
733 stridx
= *(WORD
*)ptr
;
735 *name
= assembly_dup_str(assembly
, stridx
);
737 return E_OUTOFMEMORY
;
742 HRESULT
assembly_get_path(const ASSEMBLY
*assembly
, LPWSTR
*path
)
744 LPWSTR cpy
= HeapAlloc(GetProcessHeap(), 0, (strlenW(assembly
->path
) + 1) * sizeof(WCHAR
));
747 strcpyW(cpy
, assembly
->path
);
749 return E_OUTOFMEMORY
;
754 HRESULT
assembly_get_version(ASSEMBLY
*assembly
, LPWSTR
*version
)
756 static const WCHAR format
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
758 ASSEMBLYTABLE
*asmtbl
;
763 offset
= assembly
->tables
[TableFromToken(mdtAssembly
)].offset
;
767 asmtbl
= assembly_data_offset(assembly
, offset
);
771 *version
= HeapAlloc(GetProcessHeap(), 0, sizeof(format
) + 4 * strlen("65535") * sizeof(WCHAR
));
773 return E_OUTOFMEMORY
;
775 sprintfW(*version
, format
, asmtbl
->MajorVersion
, asmtbl
->MinorVersion
,
776 asmtbl
->BuildNumber
, asmtbl
->RevisionNumber
);
781 PEKIND
assembly_get_architecture(ASSEMBLY
*assembly
)
783 if ((assembly
->corhdr
->MajorRuntimeVersion
== 2) && (assembly
->corhdr
->MinorRuntimeVersion
== 0))
784 return peNone
; /* .NET 1.x assembly */
786 if (assembly
->nthdr
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR64_MAGIC
)
787 return peAMD64
; /* AMD64/IA64 assembly */
789 if ((assembly
->corhdr
->Flags
& COMIMAGE_FLAGS_ILONLY
) && !(assembly
->corhdr
->Flags
& COMIMAGE_FLAGS_32BITREQUIRED
))
790 return peMSIL
; /* MSIL assembly */
792 return peI386
; /* x86 assembly */
795 static BYTE
*assembly_get_blob(ASSEMBLY
*assembly
, DWORD index
, ULONG
*size
)
797 return GetData(&assembly
->blobs
[index
], size
);
800 HRESULT
assembly_get_pubkey_token(ASSEMBLY
*assembly
, LPWSTR
*token
)
804 BYTE
*hashdata
, *pubkey
, *ptr
;
807 BYTE tokbytes
[BYTES_PER_TOKEN
];
814 offset
= assembly
->tables
[TableFromToken(mdtAssembly
)].offset
;
818 ptr
= assembly_data_offset(assembly
, offset
);
822 ptr
+= FIELD_OFFSET(ASSEMBLYTABLE
, PublicKey
);
823 if (assembly
->blobsz
== sizeof(DWORD
))
828 pubkey
= assembly_get_blob(assembly
, idx
, &size
);
830 if (!CryptAcquireContextA(&crypt
, NULL
, NULL
, PROV_RSA_FULL
,
831 CRYPT_VERIFYCONTEXT
))
834 if (!CryptCreateHash(crypt
, CALG_SHA1
, 0, 0, &hash
))
837 if (!CryptHashData(hash
, pubkey
, size
, 0))
841 if (!CryptGetHashParam(hash
, HP_HASHVAL
, NULL
, &size
, 0))
844 hashdata
= HeapAlloc(GetProcessHeap(), 0, size
);
851 if (!CryptGetHashParam(hash
, HP_HASHVAL
, hashdata
, &size
, 0))
854 for (i
= size
- 1; i
>= size
- 8; i
--)
855 tokbytes
[size
- i
- 1] = hashdata
[i
];
857 tok
= HeapAlloc(GetProcessHeap(), 0, (TOKEN_LENGTH
+ 1) * sizeof(WCHAR
));
864 token_to_str(tokbytes
, tok
);
870 HeapFree(GetProcessHeap(), 0, hashdata
);
871 CryptDestroyHash(hash
);
872 CryptReleaseContext(crypt
, 0);
877 HRESULT
assembly_get_runtime_version(ASSEMBLY
*assembly
, LPSTR
*version
)
879 *version
= assembly
->metadatahdr
->Version
;
883 HRESULT
assembly_get_external_files(ASSEMBLY
*assembly
, LPWSTR
**files
, DWORD
*count
)
893 offset
= assembly
->tables
[TableFromToken(mdtFile
)].offset
;
897 ptr
= assembly_data_offset(assembly
, offset
);
901 num_rows
= assembly
->tables
[TableFromToken(mdtFile
)].rows
;
905 ret
= HeapAlloc(GetProcessHeap(), 0, num_rows
* sizeof(WCHAR
*));
907 return E_OUTOFMEMORY
;
909 for (i
= 0; i
< num_rows
; i
++)
911 ptr
+= sizeof(DWORD
); /* skip Flags field */
912 if (assembly
->stringsz
== sizeof(DWORD
))
917 ret
[i
] = assembly_dup_str(assembly
, idx
);
920 for (; i
>= 0; i
--) HeapFree(GetProcessHeap(), 0, ret
[i
]);
921 HeapFree(GetProcessHeap(), 0, ret
);
922 return E_OUTOFMEMORY
;
924 ptr
+= assembly
->stringsz
; /* skip Name field */
925 ptr
+= assembly
->blobsz
; /* skip Hash field */