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 #define WIN32_NO_STATUS
23 #define COM_NO_WINDOWS_H
30 //#include "winuser.h"
38 #include "fusionpriv.h"
39 #include <wine/debug.h>
40 #include <wine/unicode.h>
42 #define TableFromToken(tk) (TypeFromToken(tk) >> 24)
43 #define TokenFromTable(idx) (idx << 24)
45 #define MAX_CLR_TABLES 64
47 #define MD_STRINGS_BIT 0x1
48 #define MD_GUIDS_BIT 0x2
49 #define MD_BLOBS_BIT 0x4
51 typedef struct tagCLRTABLE
65 IMAGE_NT_HEADERS
*nthdr
;
66 IMAGE_COR20_HEADER
*corhdr
;
68 METADATAHDR
*metadatahdr
;
70 METADATATABLESHDR
*tableshdr
;
73 CLRTABLE tables
[MAX_CLR_TABLES
];
83 static DWORD
rva_to_offset(IMAGE_NT_HEADERS
*nthdrs
, DWORD rva
)
85 DWORD offset
= rva
, limit
;
86 IMAGE_SECTION_HEADER
*img
;
89 img
= IMAGE_FIRST_SECTION(nthdrs
);
91 if (rva
< img
->PointerToRawData
)
94 for (i
= 0; i
< nthdrs
->FileHeader
.NumberOfSections
; i
++)
96 if (img
[i
].SizeOfRawData
)
97 limit
= img
[i
].SizeOfRawData
;
99 limit
= img
[i
].Misc
.VirtualSize
;
101 if (rva
>= img
[i
].VirtualAddress
&&
102 rva
< (img
[i
].VirtualAddress
+ limit
))
104 if (img
[i
].PointerToRawData
!= 0)
106 offset
-= img
[i
].VirtualAddress
;
107 offset
+= img
[i
].PointerToRawData
;
117 static BYTE
*GetData(BYTE
*pData
, ULONG
*pLength
)
119 if ((*pData
& 0x80) == 0x00)
121 *pLength
= (*pData
& 0x7f);
125 if ((*pData
& 0xC0) == 0x80)
127 *pLength
= ((*pData
& 0x3f) << 8 | *(pData
+ 1));
131 if ((*pData
& 0xE0) == 0xC0)
133 *pLength
= ((*pData
& 0x1f) << 24 | *(pData
+ 1) << 16 |
134 *(pData
+ 2) << 8 | *(pData
+ 3));
138 *pLength
= (ULONG
)-1;
142 static VOID
*assembly_data_offset(ASSEMBLY
*assembly
, ULONG offset
)
144 return &assembly
->data
[offset
];
147 #define MAX_TABLES_WORD 0xFFFF
148 #define MAX_TABLES_1BIT_ENCODE 32767
149 #define MAX_TABLES_2BIT_ENCODE 16383
150 #define MAX_TABLES_3BIT_ENCODE 8191
151 #define MAX_TABLES_5BIT_ENCODE 2047
153 static inline ULONG
get_table_size(const ASSEMBLY
*assembly
, DWORD index
)
158 switch (TokenFromTable(index
))
162 size
= sizeof(MODULETABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
163 2 * (assembly
->guidsz
- sizeof(WORD
));
168 size
= sizeof(TYPEREFTABLE
) + 2 * (assembly
->stringsz
- sizeof(WORD
));
170 /* ResolutionScope:ResolutionScope */
171 tables
= max(assembly
->tables
[TableFromToken(mdtModule
)].rows
,
172 assembly
->tables
[TableFromToken(mdtModuleRef
)].rows
);
173 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtAssemblyRef
)].rows
);
174 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
);
175 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
180 size
= sizeof(TYPEDEFTABLE
) + 2 * (assembly
->stringsz
- sizeof(WORD
));
182 /* Extends:TypeDefOrRef */
183 tables
= max(assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
,
184 assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
);
185 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeSpec
)].rows
);
186 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
188 size
+= (assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
>
189 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
190 size
+= (assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
>
191 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
196 size
= sizeof(FIELDTABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
197 (assembly
->blobsz
- sizeof(WORD
));
202 size
= sizeof(METHODDEFTABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
203 (assembly
->blobsz
- sizeof(WORD
));
205 size
+= (assembly
->tables
[TableFromToken(mdtParamDef
)].rows
>
206 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
211 size
= sizeof(PARAMTABLE
) + (assembly
->stringsz
- sizeof(WORD
));
214 case mdtInterfaceImpl
:
216 size
= sizeof(INTERFACEIMPLTABLE
);
218 /* Interface:TypeDefOrRef */
219 tables
= max(assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
,
220 assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
);
221 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeSpec
)].rows
);
222 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
227 size
= sizeof(MEMBERREFTABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
228 (assembly
->blobsz
- sizeof(WORD
));
230 /* Class:MemberRefParent */
231 tables
= max(assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
,
232 assembly
->tables
[TableFromToken(mdtModuleRef
)].rows
);
233 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
);
234 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeSpec
)].rows
);
235 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
);
236 size
+= (tables
> MAX_TABLES_3BIT_ENCODE
) ? sizeof(WORD
) : 0;
239 case 0x0B000000: /* FIXME */
241 size
= sizeof(CONSTANTTABLE
) + (assembly
->blobsz
- sizeof(WORD
));
243 /* Parent:HasConstant */
244 tables
= max(assembly
->tables
[TableFromToken(mdtParamDef
)].rows
,
245 assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
);
246 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtProperty
)].rows
);
247 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
250 case mdtCustomAttribute
:
252 size
= sizeof(CUSTOMATTRIBUTETABLE
) + (assembly
->blobsz
- sizeof(WORD
));
254 /* Parent:HasCustomAttribute */
255 tables
= max(assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
,
256 assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
);
257 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
);
258 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
);
259 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtParamDef
)].rows
);
260 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtInterfaceImpl
)].rows
);
261 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtMemberRef
)].rows
);
262 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtPermission
)].rows
);
263 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtProperty
)].rows
);
264 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtEvent
)].rows
);
265 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtSignature
)].rows
);
266 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtModuleRef
)].rows
);
267 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeSpec
)].rows
);
268 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtAssembly
)].rows
);
269 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtFile
)].rows
);
270 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtExportedType
)].rows
);
271 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtManifestResource
)].rows
);
272 size
+= (tables
> MAX_TABLES_5BIT_ENCODE
) ? sizeof(WORD
) : 0;
274 /* Type:CustomAttributeType */
275 tables
= max(assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
,
276 assembly
->tables
[TableFromToken(mdtMemberRef
)].rows
);
277 size
+= (tables
> MAX_TABLES_3BIT_ENCODE
) ? sizeof(WORD
) : 0;
280 case 0x0D000000: /* FIXME */
282 size
= sizeof(FIELDMARSHALTABLE
) + (assembly
->blobsz
- sizeof(WORD
));
284 /* Parent:HasFieldMarshal */
285 tables
= max(assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
,
286 assembly
->tables
[TableFromToken(mdtParamDef
)].rows
);
287 size
+= (tables
> MAX_TABLES_1BIT_ENCODE
) ? sizeof(WORD
) : 0;
292 size
= sizeof(DECLSECURITYTABLE
) + (assembly
->blobsz
- sizeof(WORD
));
294 /* Parent:HasDeclSecurity */
295 tables
= max(assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
,
296 assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
);
297 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtAssembly
)].rows
);
298 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
301 case 0x0F000000: /* FIXME */
303 size
= sizeof(CLASSLAYOUTTABLE
);
304 size
+= (assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
>
305 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
308 case 0x10000000: /* FIXME */
310 size
= sizeof(FIELDLAYOUTTABLE
);
311 size
+= (assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
>
312 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
317 size
= sizeof(STANDALONESIGTABLE
) + (assembly
->blobsz
- sizeof(WORD
));
320 case 0x12000000: /* FIXME */
322 size
= sizeof(EVENTMAPTABLE
);
323 size
+= (assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
>
324 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
325 size
+= (assembly
->tables
[TableFromToken(mdtEvent
)].rows
>
326 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
331 size
= sizeof(EVENTTABLE
) + (assembly
->stringsz
- sizeof(WORD
));
333 /* EventType:TypeDefOrRef */
334 tables
= max(assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
,
335 assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
);
336 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeSpec
)].rows
);
337 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
340 case 0x15000000:/* FIXME */
342 size
= sizeof(PROPERTYMAPTABLE
);
343 size
+= (assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
>
344 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
345 size
+= (assembly
->tables
[TableFromToken(mdtProperty
)].rows
>
346 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
351 size
= sizeof(PROPERTYTABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
352 (assembly
->blobsz
- sizeof(WORD
));
355 case 0x18000000: /* FIXME */
357 size
= sizeof(METHODSEMANTICSTABLE
);
359 /* Association:HasSemantics */
360 tables
= max(assembly
->tables
[TableFromToken(mdtEvent
)].rows
,
361 assembly
->tables
[TableFromToken(mdtProperty
)].rows
);
362 size
+= (tables
> MAX_TABLES_1BIT_ENCODE
) ? sizeof(WORD
) : 0;
364 size
+= (assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
>
365 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
368 case 0x19000000: /* FIXME */
370 size
= sizeof(METHODIMPLTABLE
);
372 /* MethodBody:MethodDefOrRef, MethodDeclaration:MethodDefOrRef */
373 tables
= max(assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
,
374 assembly
->tables
[TableFromToken(mdtMemberRef
)].rows
);
375 size
+= (tables
> MAX_TABLES_1BIT_ENCODE
) ? 2 * sizeof(WORD
) : 0;
377 size
+= (assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
>
378 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
383 size
= sizeof(MODULEREFTABLE
) + (assembly
->stringsz
- sizeof(WORD
));
388 size
= sizeof(TYPESPECTABLE
) + (assembly
->blobsz
- sizeof(WORD
));
391 case 0x1C000000: /* FIXME */
393 size
= sizeof(IMPLMAPTABLE
) + (assembly
->stringsz
- sizeof(WORD
));
395 /* MemberForwarded:MemberForwarded */
396 tables
= max(assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
,
397 assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
);
398 size
+= (tables
> MAX_TABLES_1BIT_ENCODE
) ? sizeof(WORD
) : 0;
400 size
+= (assembly
->tables
[TableFromToken(mdtModuleRef
)].rows
>
401 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
404 case 0x1D000000: /* FIXME */
406 size
= sizeof(FIELDRVATABLE
);
407 size
+= (assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
>
408 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
413 size
= sizeof(ASSEMBLYTABLE
) + 2 * (assembly
->stringsz
- sizeof(WORD
)) +
414 (assembly
->blobsz
- sizeof(WORD
));
417 case 0x20000001: /* FIXME */
419 size
= sizeof(ASSEMBLYPROCESSORTABLE
);
422 case 0x22000000: /* FIXME */
424 size
= sizeof(ASSEMBLYOSTABLE
);
429 size
= sizeof(ASSEMBLYREFTABLE
) + 2 * (assembly
->stringsz
- sizeof(WORD
)) +
430 2 * (assembly
->blobsz
- sizeof(WORD
));
433 case 0x24000000: /* FIXME */
435 size
= sizeof(ASSEMBLYREFPROCESSORTABLE
);
436 size
+= (assembly
->tables
[TableFromToken(mdtAssemblyRef
)].rows
>
437 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
440 case 0x25000000: /* FIXME */
442 size
= sizeof(ASSEMBLYREFOSTABLE
);
443 size
+= (assembly
->tables
[TableFromToken(mdtAssemblyRef
)].rows
>
444 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
449 size
= sizeof(FILETABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
450 (assembly
->blobsz
- sizeof(WORD
));
453 case mdtExportedType
:
455 size
= sizeof(EXPORTEDTYPETABLE
) + 2 * (assembly
->stringsz
- sizeof(WORD
));
457 /* Implementation:Implementation */
458 tables
= max(assembly
->tables
[TableFromToken(mdtFile
)].rows
,
459 assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
);
460 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
463 case mdtManifestResource
:
465 size
= sizeof(MANIFESTRESTABLE
) + (assembly
->stringsz
- sizeof(WORD
));
467 /* Implementation:Implementation */
468 tables
= max(assembly
->tables
[TableFromToken(mdtFile
)].rows
,
469 assembly
->tables
[TableFromToken(mdtAssemblyRef
)].rows
);
470 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
473 case 0x29000000: /* FIXME */
475 size
= sizeof(NESTEDCLASSTABLE
);
476 size
+= (assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
>
477 MAX_TABLES_WORD
) ? 2 * sizeof(WORD
) : 0;
487 static HRESULT
parse_clr_tables(ASSEMBLY
*assembly
, ULONG offset
)
489 DWORD i
, previ
, offidx
;
493 assembly
->tableshdr
= assembly_data_offset(assembly
, currofs
);
494 if (!assembly
->tableshdr
)
497 assembly
->stringsz
= (assembly
->tableshdr
->HeapOffsetSizes
& MD_STRINGS_BIT
) ?
498 sizeof(DWORD
) : sizeof(WORD
);
499 assembly
->guidsz
= (assembly
->tableshdr
->HeapOffsetSizes
& MD_GUIDS_BIT
) ?
500 sizeof(DWORD
) : sizeof(WORD
);
501 assembly
->blobsz
= (assembly
->tableshdr
->HeapOffsetSizes
& MD_BLOBS_BIT
) ?
502 sizeof(DWORD
) : sizeof(WORD
);
504 currofs
+= sizeof(METADATATABLESHDR
);
505 assembly
->numrows
= assembly_data_offset(assembly
, currofs
);
506 if (!assembly
->numrows
)
509 assembly
->numtables
= 0;
510 for (i
= 0; i
< MAX_CLR_TABLES
; i
++)
512 if ((i
< 32 && (assembly
->tableshdr
->MaskValid
.u
.LowPart
>> i
) & 1) ||
513 (i
>= 32 && (assembly
->tableshdr
->MaskValid
.u
.HighPart
>> i
) & 1))
515 assembly
->numtables
++;
519 currofs
+= assembly
->numtables
* sizeof(DWORD
);
520 memset(assembly
->tables
, -1, MAX_CLR_TABLES
* sizeof(CLRTABLE
));
522 if (assembly
->tableshdr
->MaskValid
.u
.LowPart
& 1)
523 assembly
->tables
[0].offset
= currofs
;
526 for (i
= 0; i
< MAX_CLR_TABLES
; i
++)
528 if ((i
< 32 && (assembly
->tableshdr
->MaskValid
.u
.LowPart
>> i
) & 1) ||
529 (i
>= 32 && (assembly
->tableshdr
->MaskValid
.u
.HighPart
>> i
) & 1))
531 assembly
->tables
[i
].rows
= assembly
->numrows
[offidx
];
538 for (i
= 1; i
< MAX_CLR_TABLES
; i
++)
540 if ((i
< 32 && (assembly
->tableshdr
->MaskValid
.u
.LowPart
>> i
) & 1) ||
541 (i
>= 32 && (assembly
->tableshdr
->MaskValid
.u
.HighPart
>> i
) & 1))
543 currofs
+= get_table_size(assembly
, previ
) * assembly
->numrows
[offidx
- 1];
544 assembly
->tables
[i
].offset
= currofs
;
553 static HRESULT
parse_metadata_header(ASSEMBLY
*assembly
, DWORD
*hdrsz
)
555 METADATAHDR
*metadatahdr
;
560 rva
= assembly
->corhdr
->MetaData
.VirtualAddress
;
561 ptr
= ImageRvaToVa(assembly
->nthdr
, assembly
->data
, rva
, NULL
);
565 metadatahdr
= (METADATAHDR
*)ptr
;
567 assembly
->metadatahdr
= HeapAlloc(GetProcessHeap(), 0, sizeof(METADATAHDR
));
568 if (!assembly
->metadatahdr
)
569 return E_OUTOFMEMORY
;
571 size
= FIELD_OFFSET(METADATAHDR
, Version
);
572 memcpy(assembly
->metadatahdr
, metadatahdr
, size
);
574 /* we don't care about the version string */
576 ofs
= FIELD_OFFSET(METADATAHDR
, Flags
);
577 ptr
+= FIELD_OFFSET(METADATAHDR
, Version
) + metadatahdr
->VersionLength
+ 1;
578 dest
= (BYTE
*)assembly
->metadatahdr
+ ofs
;
579 memcpy(dest
, ptr
, sizeof(METADATAHDR
) - ofs
);
581 *hdrsz
= sizeof(METADATAHDR
) - sizeof(LPSTR
) + metadatahdr
->VersionLength
+ 1;
586 static HRESULT
parse_clr_metadata(ASSEMBLY
*assembly
)
588 METADATASTREAMHDR
*streamhdr
;
595 hr
= parse_metadata_header(assembly
, &hdrsz
);
599 rva
= assembly
->corhdr
->MetaData
.VirtualAddress
;
600 ptr
= ImageRvaToVa(assembly
->nthdr
, assembly
->data
, rva
+ hdrsz
, NULL
);
604 for (i
= 0; i
< assembly
->metadatahdr
->Streams
; i
++)
606 streamhdr
= (METADATASTREAMHDR
*)ptr
;
607 ofs
= rva_to_offset(assembly
->nthdr
, rva
+ streamhdr
->Offset
);
609 ptr
+= sizeof(METADATASTREAMHDR
);
612 if (!lstrcmpA(stream
, "#~"))
614 hr
= parse_clr_tables(assembly
, ofs
);
618 else if (!lstrcmpA(stream
, "#Strings") || !lstrcmpA(stream
, "Strings"))
619 assembly
->strings
= assembly_data_offset(assembly
, ofs
);
620 else if (!lstrcmpA(stream
, "#Blob") || !lstrcmpA(stream
, "Blob"))
621 assembly
->blobs
= assembly_data_offset(assembly
, ofs
);
623 ptr
+= lstrlenA(stream
) + 1;
624 ptr
= (BYTE
*)(((UINT_PTR
)ptr
+ 3) & ~3); /* align on DWORD boundary */
630 static HRESULT
parse_pe_header(ASSEMBLY
*assembly
)
632 IMAGE_DATA_DIRECTORY
*datadirs
;
634 assembly
->nthdr
= ImageNtHeader(assembly
->data
);
635 if (!assembly
->nthdr
)
638 if (assembly
->nthdr
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR64_MAGIC
)
640 IMAGE_OPTIONAL_HEADER64
*opthdr
=
641 (IMAGE_OPTIONAL_HEADER64
*)&assembly
->nthdr
->OptionalHeader
;
642 datadirs
= opthdr
->DataDirectory
;
646 IMAGE_OPTIONAL_HEADER32
*opthdr
=
647 (IMAGE_OPTIONAL_HEADER32
*)&assembly
->nthdr
->OptionalHeader
;
648 datadirs
= opthdr
->DataDirectory
;
654 if (!datadirs
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
||
655 !datadirs
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
)
660 assembly
->corhdr
= ImageRvaToVa(assembly
->nthdr
, assembly
->data
,
661 datadirs
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
, NULL
);
662 if (!assembly
->corhdr
)
668 HRESULT
assembly_create(ASSEMBLY
**out
, LPCWSTR file
)
675 assembly
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ASSEMBLY
));
677 return E_OUTOFMEMORY
;
679 assembly
->path
= strdupW(file
);
686 assembly
->hfile
= CreateFileW(file
, GENERIC_READ
, FILE_SHARE_READ
,
687 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
688 if (assembly
->hfile
== INVALID_HANDLE_VALUE
)
690 hr
= HRESULT_FROM_WIN32(GetLastError());
694 assembly
->hmap
= CreateFileMappingW(assembly
->hfile
, NULL
, PAGE_READONLY
,
698 hr
= HRESULT_FROM_WIN32(GetLastError());
702 assembly
->data
= MapViewOfFile(assembly
->hmap
, FILE_MAP_READ
, 0, 0, 0);
705 hr
= HRESULT_FROM_WIN32(GetLastError());
709 hr
= parse_pe_header(assembly
);
710 if (FAILED(hr
)) goto failed
;
712 hr
= parse_clr_metadata(assembly
);
713 if (FAILED(hr
)) goto failed
;
719 assembly_release(assembly
);
723 HRESULT
assembly_release(ASSEMBLY
*assembly
)
728 HeapFree(GetProcessHeap(), 0, assembly
->metadatahdr
);
729 HeapFree(GetProcessHeap(), 0, assembly
->path
);
730 UnmapViewOfFile(assembly
->data
);
731 CloseHandle(assembly
->hmap
);
732 CloseHandle(assembly
->hfile
);
733 HeapFree(GetProcessHeap(), 0, assembly
);
738 static LPWSTR
assembly_dup_str(const ASSEMBLY
*assembly
, DWORD index
)
742 LPCSTR str
= (LPCSTR
)&assembly
->strings
[index
];
744 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
746 if ((cpy
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))))
747 MultiByteToWideChar(CP_ACP
, 0, str
, -1, cpy
, len
);
752 HRESULT
assembly_get_name(ASSEMBLY
*assembly
, LPWSTR
*name
)
758 offset
= assembly
->tables
[TableFromToken(mdtAssembly
)].offset
;
762 ptr
= assembly_data_offset(assembly
, offset
);
766 ptr
+= FIELD_OFFSET(ASSEMBLYTABLE
, PublicKey
) + assembly
->blobsz
;
767 if (assembly
->stringsz
== sizeof(DWORD
))
768 stridx
= *((DWORD
*)ptr
);
770 stridx
= *((WORD
*)ptr
);
772 *name
= assembly_dup_str(assembly
, stridx
);
774 return E_OUTOFMEMORY
;
779 HRESULT
assembly_get_path(const ASSEMBLY
*assembly
, LPWSTR
*path
)
781 LPWSTR cpy
= HeapAlloc(GetProcessHeap(), 0, (strlenW(assembly
->path
) + 1) * sizeof(WCHAR
));
784 strcpyW(cpy
, assembly
->path
);
786 return E_OUTOFMEMORY
;
791 HRESULT
assembly_get_version(ASSEMBLY
*assembly
, LPWSTR
*version
)
793 static const WCHAR format
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
795 ASSEMBLYTABLE
*asmtbl
;
800 offset
= assembly
->tables
[TableFromToken(mdtAssembly
)].offset
;
804 asmtbl
= assembly_data_offset(assembly
, offset
);
808 *version
= HeapAlloc(GetProcessHeap(), 0, sizeof(format
) + 4 * strlen("65535") * sizeof(WCHAR
));
810 return E_OUTOFMEMORY
;
812 sprintfW(*version
, format
, asmtbl
->MajorVersion
, asmtbl
->MinorVersion
,
813 asmtbl
->BuildNumber
, asmtbl
->RevisionNumber
);
818 BYTE
assembly_get_architecture(ASSEMBLY
*assembly
)
820 if ((assembly
->corhdr
->MajorRuntimeVersion
== 2) && (assembly
->corhdr
->MinorRuntimeVersion
== 0))
821 return 0; /* .NET 1.x assembly */
823 if (assembly
->nthdr
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR64_MAGIC
)
824 return peAMD64
; /* AMD64/IA64 assembly */
826 if ((assembly
->corhdr
->Flags
& COMIMAGE_FLAGS_ILONLY
) && !(assembly
->corhdr
->Flags
& COMIMAGE_FLAGS_32BITREQUIRED
))
827 return peMSIL
; /* MSIL assembly */
829 return peI386
; /* x86 assembly */
832 static BYTE
*assembly_get_blob(ASSEMBLY
*assembly
, WORD index
, ULONG
*size
)
834 return GetData(&assembly
->blobs
[index
], size
);
837 HRESULT
assembly_get_pubkey_token(ASSEMBLY
*assembly
, LPWSTR
*token
)
839 ASSEMBLYTABLE
*asmtbl
;
846 BYTE tokbytes
[BYTES_PER_TOKEN
];
852 offset
= assembly
->tables
[TableFromToken(mdtAssembly
)].offset
;
856 asmtbl
= assembly_data_offset(assembly
, offset
);
860 pubkey
= assembly_get_blob(assembly
, asmtbl
->PublicKey
, &size
);
862 if (!CryptAcquireContextA(&crypt
, NULL
, NULL
, PROV_RSA_FULL
,
863 CRYPT_VERIFYCONTEXT
))
866 if (!CryptCreateHash(crypt
, CALG_SHA1
, 0, 0, &hash
))
869 if (!CryptHashData(hash
, pubkey
, size
, 0))
873 if (!CryptGetHashParam(hash
, HP_HASHVAL
, NULL
, &size
, 0))
876 hashdata
= HeapAlloc(GetProcessHeap(), 0, size
);
883 if (!CryptGetHashParam(hash
, HP_HASHVAL
, hashdata
, &size
, 0))
886 for (i
= size
- 1; i
>= size
- 8; i
--)
887 tokbytes
[size
- i
- 1] = hashdata
[i
];
889 tok
= HeapAlloc(GetProcessHeap(), 0, (TOKEN_LENGTH
+ 1) * sizeof(WCHAR
));
896 token_to_str(tokbytes
, tok
);
902 HeapFree(GetProcessHeap(), 0, hashdata
);
903 CryptDestroyHash(hash
);
904 CryptReleaseContext(crypt
, 0);