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
25 #define WIN32_NO_STATUS
36 #include "fusionpriv.h"
37 #include "wine/debug.h"
39 #define TableFromToken(tk) (TypeFromToken(tk) >> 24)
40 #define TokenFromTable(idx) (idx << 24)
42 #define MAX_CLR_TABLES 64
44 #define MD_STRINGS_BIT 0x1
45 #define MD_GUIDS_BIT 0x2
46 #define MD_BLOBS_BIT 0x4
48 typedef struct tagCLRTABLE
62 IMAGE_NT_HEADERS
*nthdr
;
63 IMAGE_COR20_HEADER
*corhdr
;
65 METADATAHDR
*metadatahdr
;
67 METADATATABLESHDR
*tableshdr
;
70 CLRTABLE tables
[MAX_CLR_TABLES
];
80 static DWORD
rva_to_offset(IMAGE_NT_HEADERS
*nthdrs
, DWORD rva
)
82 DWORD offset
= rva
, limit
;
83 IMAGE_SECTION_HEADER
*img
;
86 img
= IMAGE_FIRST_SECTION(nthdrs
);
88 if (rva
< img
->PointerToRawData
)
91 for (i
= 0; i
< nthdrs
->FileHeader
.NumberOfSections
; i
++)
93 if (img
[i
].SizeOfRawData
)
94 limit
= img
[i
].SizeOfRawData
;
96 limit
= img
[i
].Misc
.VirtualSize
;
98 if (rva
>= img
[i
].VirtualAddress
&&
99 rva
< (img
[i
].VirtualAddress
+ limit
))
101 if (img
[i
].PointerToRawData
!= 0)
103 offset
-= img
[i
].VirtualAddress
;
104 offset
+= img
[i
].PointerToRawData
;
114 static BYTE
*GetData(BYTE
*pData
, ULONG
*pLength
)
116 if ((*pData
& 0x80) == 0x00)
118 *pLength
= (*pData
& 0x7f);
122 if ((*pData
& 0xC0) == 0x80)
124 *pLength
= ((*pData
& 0x3f) << 8 | *(pData
+ 1));
128 if ((*pData
& 0xE0) == 0xC0)
130 *pLength
= ((*pData
& 0x1f) << 24 | *(pData
+ 1) << 16 |
131 *(pData
+ 2) << 8 | *(pData
+ 3));
135 *pLength
= (ULONG
)-1;
139 static VOID
*assembly_data_offset(ASSEMBLY
*assembly
, ULONG offset
)
141 return &assembly
->data
[offset
];
144 #define MAX_TABLES_WORD 0xFFFF
145 #define MAX_TABLES_1BIT_ENCODE 32767
146 #define MAX_TABLES_2BIT_ENCODE 16383
147 #define MAX_TABLES_3BIT_ENCODE 8191
148 #define MAX_TABLES_5BIT_ENCODE 2047
150 static inline ULONG
get_table_size(const ASSEMBLY
*assembly
, DWORD index
)
155 switch (TokenFromTable(index
))
159 size
= sizeof(MODULETABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
160 2 * (assembly
->guidsz
- sizeof(WORD
));
165 size
= sizeof(TYPEREFTABLE
) + 2 * (assembly
->stringsz
- sizeof(WORD
));
167 /* ResolutionScope:ResolutionScope */
168 tables
= max(assembly
->tables
[TableFromToken(mdtModule
)].rows
,
169 assembly
->tables
[TableFromToken(mdtModuleRef
)].rows
);
170 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtAssemblyRef
)].rows
);
171 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
);
172 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
177 size
= sizeof(TYPEDEFTABLE
) + 2 * (assembly
->stringsz
- sizeof(WORD
));
179 /* Extends:TypeDefOrRef */
180 tables
= max(assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
,
181 assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
);
182 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeSpec
)].rows
);
183 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
185 size
+= (assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
>
186 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
187 size
+= (assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
>
188 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
193 size
= sizeof(FIELDTABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
194 (assembly
->blobsz
- sizeof(WORD
));
199 size
= sizeof(METHODDEFTABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
200 (assembly
->blobsz
- sizeof(WORD
));
202 size
+= (assembly
->tables
[TableFromToken(mdtParamDef
)].rows
>
203 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
208 size
= sizeof(PARAMTABLE
) + (assembly
->stringsz
- sizeof(WORD
));
211 case mdtInterfaceImpl
:
213 size
= sizeof(INTERFACEIMPLTABLE
);
215 /* Interface:TypeDefOrRef */
216 tables
= max(assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
,
217 assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
);
218 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeSpec
)].rows
);
219 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
224 size
= sizeof(MEMBERREFTABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
225 (assembly
->blobsz
- sizeof(WORD
));
227 /* Class:MemberRefParent */
228 tables
= max(assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
,
229 assembly
->tables
[TableFromToken(mdtModuleRef
)].rows
);
230 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
);
231 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeSpec
)].rows
);
232 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
);
233 size
+= (tables
> MAX_TABLES_3BIT_ENCODE
) ? sizeof(WORD
) : 0;
236 case 0x0B000000: /* FIXME */
238 size
= sizeof(CONSTANTTABLE
) + (assembly
->blobsz
- sizeof(WORD
));
240 /* Parent:HasConstant */
241 tables
= max(assembly
->tables
[TableFromToken(mdtParamDef
)].rows
,
242 assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
);
243 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtProperty
)].rows
);
244 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
247 case mdtCustomAttribute
:
249 size
= sizeof(CUSTOMATTRIBUTETABLE
) + (assembly
->blobsz
- sizeof(WORD
));
251 /* Parent:HasCustomAttribute */
252 tables
= max(assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
,
253 assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
);
254 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
);
255 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
);
256 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtParamDef
)].rows
);
257 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtInterfaceImpl
)].rows
);
258 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtMemberRef
)].rows
);
259 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtPermission
)].rows
);
260 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtProperty
)].rows
);
261 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtEvent
)].rows
);
262 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtSignature
)].rows
);
263 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtModuleRef
)].rows
);
264 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeSpec
)].rows
);
265 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtAssembly
)].rows
);
266 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtFile
)].rows
);
267 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtExportedType
)].rows
);
268 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtManifestResource
)].rows
);
269 size
+= (tables
> MAX_TABLES_5BIT_ENCODE
) ? sizeof(WORD
) : 0;
271 /* Type:CustomAttributeType */
272 tables
= max(assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
,
273 assembly
->tables
[TableFromToken(mdtMemberRef
)].rows
);
274 size
+= (tables
> MAX_TABLES_3BIT_ENCODE
) ? sizeof(WORD
) : 0;
277 case 0x0D000000: /* FIXME */
279 size
= sizeof(FIELDMARSHALTABLE
) + (assembly
->blobsz
- sizeof(WORD
));
281 /* Parent:HasFieldMarshal */
282 tables
= max(assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
,
283 assembly
->tables
[TableFromToken(mdtParamDef
)].rows
);
284 size
+= (tables
> MAX_TABLES_1BIT_ENCODE
) ? sizeof(WORD
) : 0;
289 size
= sizeof(DECLSECURITYTABLE
) + (assembly
->blobsz
- sizeof(WORD
));
291 /* Parent:HasDeclSecurity */
292 tables
= max(assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
,
293 assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
);
294 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtAssembly
)].rows
);
295 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
298 case 0x0F000000: /* FIXME */
300 size
= sizeof(CLASSLAYOUTTABLE
);
301 size
+= (assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
>
302 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
305 case 0x10000000: /* FIXME */
307 size
= sizeof(FIELDLAYOUTTABLE
);
308 size
+= (assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
>
309 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
314 size
= sizeof(STANDALONESIGTABLE
) + (assembly
->blobsz
- sizeof(WORD
));
317 case 0x12000000: /* FIXME */
319 size
= sizeof(EVENTMAPTABLE
);
320 size
+= (assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
>
321 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
322 size
+= (assembly
->tables
[TableFromToken(mdtEvent
)].rows
>
323 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
328 size
= sizeof(EVENTTABLE
) + (assembly
->stringsz
- sizeof(WORD
));
330 /* EventType:TypeDefOrRef */
331 tables
= max(assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
,
332 assembly
->tables
[TableFromToken(mdtTypeRef
)].rows
);
333 tables
= max(tables
, assembly
->tables
[TableFromToken(mdtTypeSpec
)].rows
);
334 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
337 case 0x15000000:/* FIXME */
339 size
= sizeof(PROPERTYMAPTABLE
);
340 size
+= (assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
>
341 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
342 size
+= (assembly
->tables
[TableFromToken(mdtProperty
)].rows
>
343 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
348 size
= sizeof(PROPERTYTABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
349 (assembly
->blobsz
- sizeof(WORD
));
352 case 0x18000000: /* FIXME */
354 size
= sizeof(METHODSEMANTICSTABLE
);
356 /* Association:HasSemantics */
357 tables
= max(assembly
->tables
[TableFromToken(mdtEvent
)].rows
,
358 assembly
->tables
[TableFromToken(mdtProperty
)].rows
);
359 size
+= (tables
> MAX_TABLES_1BIT_ENCODE
) ? sizeof(WORD
) : 0;
361 size
+= (assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
>
362 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
365 case 0x19000000: /* FIXME */
367 size
= sizeof(METHODIMPLTABLE
);
369 /* MethodBody:MethodDefOrRef, MethodDeclaration:MethodDefOrRef */
370 tables
= max(assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
,
371 assembly
->tables
[TableFromToken(mdtMemberRef
)].rows
);
372 size
+= (tables
> MAX_TABLES_1BIT_ENCODE
) ? 2 * sizeof(WORD
) : 0;
374 size
+= (assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
>
375 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
380 size
= sizeof(MODULEREFTABLE
) + (assembly
->stringsz
- sizeof(WORD
));
385 size
= sizeof(TYPESPECTABLE
) + (assembly
->blobsz
- sizeof(WORD
));
388 case 0x1C000000: /* FIXME */
390 size
= sizeof(IMPLMAPTABLE
) + (assembly
->stringsz
- sizeof(WORD
));
392 /* MemberForwarded:MemberForwarded */
393 tables
= max(assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
,
394 assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
);
395 size
+= (tables
> MAX_TABLES_1BIT_ENCODE
) ? sizeof(WORD
) : 0;
397 size
+= (assembly
->tables
[TableFromToken(mdtModuleRef
)].rows
>
398 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
401 case 0x1D000000: /* FIXME */
403 size
= sizeof(FIELDRVATABLE
);
404 size
+= (assembly
->tables
[TableFromToken(mdtFieldDef
)].rows
>
405 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
410 size
= sizeof(ASSEMBLYTABLE
) + 2 * (assembly
->stringsz
- sizeof(WORD
)) +
411 (assembly
->blobsz
- sizeof(WORD
));
414 case 0x20000001: /* FIXME */
416 size
= sizeof(ASSEMBLYPROCESSORTABLE
);
419 case 0x22000000: /* FIXME */
421 size
= sizeof(ASSEMBLYOSTABLE
);
426 size
= sizeof(ASSEMBLYREFTABLE
) + 2 * (assembly
->stringsz
- sizeof(WORD
)) +
427 2 * (assembly
->blobsz
- sizeof(WORD
));
430 case 0x24000000: /* FIXME */
432 size
= sizeof(ASSEMBLYREFPROCESSORTABLE
);
433 size
+= (assembly
->tables
[TableFromToken(mdtAssemblyRef
)].rows
>
434 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
437 case 0x25000000: /* FIXME */
439 size
= sizeof(ASSEMBLYREFOSTABLE
);
440 size
+= (assembly
->tables
[TableFromToken(mdtAssemblyRef
)].rows
>
441 MAX_TABLES_WORD
) ? sizeof(WORD
) : 0;
446 size
= sizeof(FILETABLE
) + (assembly
->stringsz
- sizeof(WORD
)) +
447 (assembly
->blobsz
- sizeof(WORD
));
450 case mdtExportedType
:
452 size
= sizeof(EXPORTEDTYPETABLE
) + 2 * (assembly
->stringsz
- sizeof(WORD
));
454 /* Implementation:Implementation */
455 tables
= max(assembly
->tables
[TableFromToken(mdtFile
)].rows
,
456 assembly
->tables
[TableFromToken(mdtMethodDef
)].rows
);
457 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
460 case mdtManifestResource
:
462 size
= sizeof(MANIFESTRESTABLE
) + (assembly
->stringsz
- sizeof(WORD
));
464 /* Implementation:Implementation */
465 tables
= max(assembly
->tables
[TableFromToken(mdtFile
)].rows
,
466 assembly
->tables
[TableFromToken(mdtAssemblyRef
)].rows
);
467 size
+= (tables
> MAX_TABLES_2BIT_ENCODE
) ? sizeof(WORD
) : 0;
470 case 0x29000000: /* FIXME */
472 size
= sizeof(NESTEDCLASSTABLE
);
473 size
+= (assembly
->tables
[TableFromToken(mdtTypeDef
)].rows
>
474 MAX_TABLES_WORD
) ? 2 * sizeof(WORD
) : 0;
484 static HRESULT
parse_clr_tables(ASSEMBLY
*assembly
, ULONG offset
)
491 assembly
->tableshdr
= assembly_data_offset(assembly
, currofs
);
492 if (!assembly
->tableshdr
)
495 assembly
->stringsz
= (assembly
->tableshdr
->HeapOffsetSizes
& MD_STRINGS_BIT
) ?
496 sizeof(DWORD
) : sizeof(WORD
);
497 assembly
->guidsz
= (assembly
->tableshdr
->HeapOffsetSizes
& MD_GUIDS_BIT
) ?
498 sizeof(DWORD
) : sizeof(WORD
);
499 assembly
->blobsz
= (assembly
->tableshdr
->HeapOffsetSizes
& MD_BLOBS_BIT
) ?
500 sizeof(DWORD
) : sizeof(WORD
);
502 currofs
+= sizeof(METADATATABLESHDR
);
503 assembly
->numrows
= assembly_data_offset(assembly
, currofs
);
504 if (!assembly
->numrows
)
507 memset(assembly
->tables
, -1, MAX_CLR_TABLES
* sizeof(CLRTABLE
));
509 for (i
= count
= 0, mask
= 1; i
< MAX_CLR_TABLES
; i
++, mask
<<= 1)
511 if (assembly
->tableshdr
->MaskValid
.QuadPart
& mask
)
512 assembly
->tables
[i
].rows
= assembly
->numrows
[count
++];
514 assembly
->numtables
= count
;
515 currofs
+= assembly
->numtables
* sizeof(DWORD
);
517 for (i
= 0, mask
= 1; i
< MAX_CLR_TABLES
; i
++, mask
<<= 1)
519 if (assembly
->tableshdr
->MaskValid
.QuadPart
& mask
)
521 assembly
->tables
[i
].offset
= currofs
;
522 currofs
+= get_table_size(assembly
, i
) * assembly
->tables
[i
].rows
;
529 static HRESULT
parse_metadata_header(ASSEMBLY
*assembly
, DWORD
*hdrsz
)
531 METADATAHDR
*metadatahdr
;
536 rva
= assembly
->corhdr
->MetaData
.VirtualAddress
;
537 ptr
= ImageRvaToVa(assembly
->nthdr
, assembly
->data
, rva
, NULL
);
541 metadatahdr
= (METADATAHDR
*)ptr
;
543 if (!(assembly
->metadatahdr
= heap_alloc(sizeof(*assembly
->metadatahdr
)))) return E_OUTOFMEMORY
;
545 size
= FIELD_OFFSET(METADATAHDR
, Version
);
546 memcpy(assembly
->metadatahdr
, metadatahdr
, size
);
548 assembly
->metadatahdr
->Version
= (LPSTR
)&metadatahdr
->Version
;
550 ofs
= FIELD_OFFSET(METADATAHDR
, Flags
);
551 ptr
+= FIELD_OFFSET(METADATAHDR
, Version
) + metadatahdr
->VersionLength
+ 1;
552 dest
= (BYTE
*)assembly
->metadatahdr
+ ofs
;
553 memcpy(dest
, ptr
, sizeof(METADATAHDR
) - ofs
);
555 *hdrsz
= sizeof(METADATAHDR
) - sizeof(LPSTR
) + metadatahdr
->VersionLength
+ 1;
560 static HRESULT
parse_clr_metadata(ASSEMBLY
*assembly
)
562 METADATASTREAMHDR
*streamhdr
;
569 hr
= parse_metadata_header(assembly
, &hdrsz
);
573 rva
= assembly
->corhdr
->MetaData
.VirtualAddress
;
574 ptr
= ImageRvaToVa(assembly
->nthdr
, assembly
->data
, rva
+ hdrsz
, NULL
);
578 for (i
= 0; i
< assembly
->metadatahdr
->Streams
; i
++)
580 streamhdr
= (METADATASTREAMHDR
*)ptr
;
581 ofs
= rva_to_offset(assembly
->nthdr
, rva
+ streamhdr
->Offset
);
583 ptr
+= sizeof(METADATASTREAMHDR
);
586 if (!lstrcmpA(stream
, "#~"))
588 hr
= parse_clr_tables(assembly
, ofs
);
592 else if (!lstrcmpA(stream
, "#Strings") || !lstrcmpA(stream
, "Strings"))
593 assembly
->strings
= assembly_data_offset(assembly
, ofs
);
594 else if (!lstrcmpA(stream
, "#Blob") || !lstrcmpA(stream
, "Blob"))
595 assembly
->blobs
= assembly_data_offset(assembly
, ofs
);
597 ptr
+= ((lstrlenA(stream
) + 1) + 3) & ~3; /* align on DWORD boundary */
603 static HRESULT
parse_pe_header(ASSEMBLY
*assembly
)
605 IMAGE_DATA_DIRECTORY
*datadirs
;
607 assembly
->nthdr
= ImageNtHeader(assembly
->data
);
608 if (!assembly
->nthdr
)
611 if (assembly
->nthdr
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR64_MAGIC
)
613 IMAGE_OPTIONAL_HEADER64
*opthdr
=
614 (IMAGE_OPTIONAL_HEADER64
*)&assembly
->nthdr
->OptionalHeader
;
615 datadirs
= opthdr
->DataDirectory
;
619 IMAGE_OPTIONAL_HEADER32
*opthdr
=
620 (IMAGE_OPTIONAL_HEADER32
*)&assembly
->nthdr
->OptionalHeader
;
621 datadirs
= opthdr
->DataDirectory
;
627 if (!datadirs
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
||
628 !datadirs
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
)
633 assembly
->corhdr
= ImageRvaToVa(assembly
->nthdr
, assembly
->data
,
634 datadirs
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
, NULL
);
635 if (!assembly
->corhdr
)
641 HRESULT
assembly_create(ASSEMBLY
**out
, LPCWSTR file
)
648 if (!(assembly
= heap_alloc_zero(sizeof(*assembly
)))) return E_OUTOFMEMORY
;
650 assembly
->path
= strdupW(file
);
657 assembly
->hfile
= CreateFileW(file
, GENERIC_READ
, FILE_SHARE_READ
,
658 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
659 if (assembly
->hfile
== INVALID_HANDLE_VALUE
)
661 hr
= HRESULT_FROM_WIN32(GetLastError());
665 assembly
->hmap
= CreateFileMappingW(assembly
->hfile
, NULL
, PAGE_READONLY
,
669 hr
= HRESULT_FROM_WIN32(GetLastError());
673 assembly
->data
= MapViewOfFile(assembly
->hmap
, FILE_MAP_READ
, 0, 0, 0);
676 hr
= HRESULT_FROM_WIN32(GetLastError());
680 hr
= parse_pe_header(assembly
);
681 if (FAILED(hr
)) goto failed
;
683 hr
= parse_clr_metadata(assembly
);
684 if (FAILED(hr
)) goto failed
;
690 assembly_release(assembly
);
694 HRESULT
assembly_release(ASSEMBLY
*assembly
)
699 heap_free(assembly
->metadatahdr
);
700 heap_free(assembly
->path
);
701 UnmapViewOfFile(assembly
->data
);
702 CloseHandle(assembly
->hmap
);
703 CloseHandle(assembly
->hfile
);
709 static LPWSTR
assembly_dup_str(const ASSEMBLY
*assembly
, DWORD index
)
713 LPCSTR str
= (LPCSTR
)&assembly
->strings
[index
];
715 len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
717 if ((cpy
= heap_alloc(len
* sizeof(WCHAR
))))
718 MultiByteToWideChar(CP_ACP
, 0, str
, -1, cpy
, len
);
723 HRESULT
assembly_get_name(ASSEMBLY
*assembly
, LPWSTR
*name
)
729 offset
= assembly
->tables
[TableFromToken(mdtAssembly
)].offset
;
733 ptr
= assembly_data_offset(assembly
, offset
);
737 ptr
+= FIELD_OFFSET(ASSEMBLYTABLE
, PublicKey
) + assembly
->blobsz
;
738 if (assembly
->stringsz
== sizeof(DWORD
))
739 stridx
= *(DWORD
*)ptr
;
741 stridx
= *(WORD
*)ptr
;
743 *name
= assembly_dup_str(assembly
, stridx
);
745 return E_OUTOFMEMORY
;
750 HRESULT
assembly_get_path(const ASSEMBLY
*assembly
, LPWSTR
*path
)
752 WCHAR
*cpy
= heap_alloc((lstrlenW(assembly
->path
) + 1) * sizeof(WCHAR
));
755 lstrcpyW(cpy
, assembly
->path
);
757 return E_OUTOFMEMORY
;
762 HRESULT
assembly_get_version(ASSEMBLY
*assembly
, LPWSTR
*version
)
764 static const WCHAR format
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
766 ASSEMBLYTABLE
*asmtbl
;
771 offset
= assembly
->tables
[TableFromToken(mdtAssembly
)].offset
;
775 asmtbl
= assembly_data_offset(assembly
, offset
);
779 if (!(*version
= heap_alloc(24 * sizeof(WCHAR
))))
780 return E_OUTOFMEMORY
;
782 swprintf(*version
, 24, format
, asmtbl
->MajorVersion
, asmtbl
->MinorVersion
,
783 asmtbl
->BuildNumber
, asmtbl
->RevisionNumber
);
788 PEKIND
assembly_get_architecture(ASSEMBLY
*assembly
)
790 if ((assembly
->corhdr
->MajorRuntimeVersion
== 2) && (assembly
->corhdr
->MinorRuntimeVersion
== 0))
791 return peNone
; /* .NET 1.x assembly */
793 if (assembly
->nthdr
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR64_MAGIC
)
794 return peAMD64
; /* AMD64/IA64 assembly */
796 if ((assembly
->corhdr
->Flags
& COMIMAGE_FLAGS_ILONLY
) && !(assembly
->corhdr
->Flags
& COMIMAGE_FLAGS_32BITREQUIRED
))
797 return peMSIL
; /* MSIL assembly */
799 return peI386
; /* x86 assembly */
802 static BYTE
*assembly_get_blob(ASSEMBLY
*assembly
, DWORD index
, ULONG
*size
)
804 return GetData(&assembly
->blobs
[index
], size
);
807 HRESULT
assembly_get_pubkey_token(ASSEMBLY
*assembly
, LPWSTR
*token
)
811 BYTE hashdata
[20], *pubkey
, *ptr
;
812 BCRYPT_ALG_HANDLE alg
;
813 BYTE tokbytes
[BYTES_PER_TOKEN
];
820 offset
= assembly
->tables
[TableFromToken(mdtAssembly
)].offset
;
824 ptr
= assembly_data_offset(assembly
, offset
);
828 ptr
+= FIELD_OFFSET(ASSEMBLYTABLE
, PublicKey
);
829 if (assembly
->blobsz
== sizeof(DWORD
))
834 pubkey
= assembly_get_blob(assembly
, idx
, &size
);
836 if (BCryptOpenAlgorithmProvider(&alg
, BCRYPT_SHA1_ALGORITHM
, MS_PRIMITIVE_PROVIDER
, 0) != STATUS_SUCCESS
)
839 if (BCryptHash(alg
, NULL
, 0, pubkey
, size
, hashdata
, sizeof(hashdata
)) != STATUS_SUCCESS
)
845 size
= sizeof(hashdata
);
846 for (i
= size
- 1; i
>= size
- 8; i
--)
847 tokbytes
[size
- i
- 1] = hashdata
[i
];
849 if (!(tok
= heap_alloc((TOKEN_LENGTH
+ 1) * sizeof(WCHAR
))))
855 token_to_str(tokbytes
, tok
);
861 BCryptCloseAlgorithmProvider(alg
, 0);
865 HRESULT
assembly_get_runtime_version(ASSEMBLY
*assembly
, LPSTR
*version
)
867 *version
= assembly
->metadatahdr
->Version
;
871 HRESULT
assembly_get_external_files(ASSEMBLY
*assembly
, LPWSTR
**files
, DWORD
*count
)
881 offset
= assembly
->tables
[TableFromToken(mdtFile
)].offset
;
885 ptr
= assembly_data_offset(assembly
, offset
);
889 num_rows
= assembly
->tables
[TableFromToken(mdtFile
)].rows
;
893 if (!(ret
= heap_alloc(num_rows
* sizeof(WCHAR
*)))) return E_OUTOFMEMORY
;
895 for (i
= 0; i
< num_rows
; i
++)
897 ptr
+= sizeof(DWORD
); /* skip Flags field */
898 if (assembly
->stringsz
== sizeof(DWORD
))
903 ret
[i
] = assembly_dup_str(assembly
, idx
);
906 for (; i
>= 0; i
--) heap_free(ret
[i
]);
908 return E_OUTOFMEMORY
;
910 ptr
+= assembly
->stringsz
; /* skip Name field */
911 ptr
+= assembly
->blobsz
; /* skip Hash field */