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 NONAMELESSUNION
36 #include "wine/list.h"
37 #include "mscoree_private.h"
39 #include "wine/debug.h"
59 typedef struct tagCLRTABLE
76 IMAGE_NT_HEADERS
*nthdr
;
77 IMAGE_COR20_HEADER
*corhdr
;
79 METADATAHDR
*metadatahdr
;
82 static void* assembly_rva_to_va(ASSEMBLY
*assembly
, ULONG rva
)
84 if (assembly
->is_mapped_file
)
85 return ImageRvaToVa(assembly
->nthdr
, assembly
->data
, rva
, NULL
);
87 return assembly
->data
+ rva
;
90 static ULONG
assembly_datadir_get_data(ASSEMBLY
*assembly
,
91 IMAGE_DATA_DIRECTORY
*datadir
, void **data
)
93 if (!datadir
->VirtualAddress
|| !datadir
->Size
)
100 *data
= assembly_rva_to_va(assembly
, datadir
->VirtualAddress
);
101 return datadir
->Size
;
105 static HRESULT
parse_metadata_header(ASSEMBLY
*assembly
, DWORD
*hdrsz
)
107 METADATAHDR
*metadatahdr
;
112 rva
= assembly
->corhdr
->MetaData
.VirtualAddress
;
113 ptr
= assembly_rva_to_va(assembly
, rva
);
117 metadatahdr
= (METADATAHDR
*)ptr
;
119 assembly
->metadatahdr
= malloc(sizeof(METADATAHDR
));
120 if (!assembly
->metadatahdr
)
121 return E_OUTOFMEMORY
;
123 size
= FIELD_OFFSET(METADATAHDR
, Version
);
124 memcpy(assembly
->metadatahdr
, metadatahdr
, size
);
126 assembly
->metadatahdr
->Version
= (LPSTR
)&metadatahdr
->Version
;
128 ofs
= FIELD_OFFSET(METADATAHDR
, Flags
);
129 ptr
+= FIELD_OFFSET(METADATAHDR
, Version
) + metadatahdr
->VersionLength
+ 1;
130 dest
= (BYTE
*)assembly
->metadatahdr
+ ofs
;
131 memcpy(dest
, ptr
, sizeof(METADATAHDR
) - ofs
);
133 *hdrsz
= sizeof(METADATAHDR
) - sizeof(LPSTR
) + metadatahdr
->VersionLength
+ 1;
138 static HRESULT
parse_clr_metadata(ASSEMBLY
*assembly
)
143 hr
= parse_metadata_header(assembly
, &hdrsz
);
150 static HRESULT
parse_pe_header(ASSEMBLY
*assembly
)
152 IMAGE_DATA_DIRECTORY
*datadirs
;
154 assembly
->nthdr
= ImageNtHeader(assembly
->data
);
155 if (!assembly
->nthdr
)
158 if (assembly
->nthdr
->OptionalHeader
.Magic
== IMAGE_NT_OPTIONAL_HDR64_MAGIC
)
160 IMAGE_OPTIONAL_HEADER64
*opthdr
=
161 (IMAGE_OPTIONAL_HEADER64
*)&assembly
->nthdr
->OptionalHeader
;
162 datadirs
= opthdr
->DataDirectory
;
166 IMAGE_OPTIONAL_HEADER32
*opthdr
=
167 (IMAGE_OPTIONAL_HEADER32
*)&assembly
->nthdr
->OptionalHeader
;
168 datadirs
= opthdr
->DataDirectory
;
174 if (!assembly_datadir_get_data(assembly
, &datadirs
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
], (void**)&assembly
->corhdr
))
180 static HRESULT
parse_headers(ASSEMBLY
*assembly
)
184 hr
= parse_pe_header(assembly
);
187 hr
= parse_clr_metadata(assembly
);
192 HRESULT
assembly_create(ASSEMBLY
**out
, LPCWSTR file
)
199 assembly
= calloc(1, sizeof(ASSEMBLY
));
201 return E_OUTOFMEMORY
;
203 assembly
->is_mapped_file
= TRUE
;
205 assembly
->path
= wcsdup(file
);
212 assembly
->hfile
= CreateFileW(file
, GENERIC_READ
, FILE_SHARE_READ
,
213 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
214 if (assembly
->hfile
== INVALID_HANDLE_VALUE
)
216 hr
= HRESULT_FROM_WIN32(GetLastError());
220 assembly
->hmap
= CreateFileMappingW(assembly
->hfile
, NULL
, PAGE_READONLY
,
224 hr
= HRESULT_FROM_WIN32(GetLastError());
228 assembly
->data
= MapViewOfFile(assembly
->hmap
, FILE_MAP_READ
, 0, 0, 0);
231 hr
= HRESULT_FROM_WIN32(GetLastError());
235 hr
= parse_headers(assembly
);
236 if (FAILED(hr
)) goto failed
;
242 assembly_release(assembly
);
246 HRESULT
assembly_from_hmodule(ASSEMBLY
**out
, HMODULE hmodule
)
253 assembly
= calloc(1, sizeof(ASSEMBLY
));
255 return E_OUTOFMEMORY
;
257 assembly
->is_mapped_file
= FALSE
;
259 assembly
->data
= (BYTE
*)hmodule
;
261 hr
= parse_headers(assembly
);
265 assembly_release(assembly
);
270 HRESULT
assembly_release(ASSEMBLY
*assembly
)
275 if (assembly
->is_mapped_file
)
277 UnmapViewOfFile(assembly
->data
);
278 CloseHandle(assembly
->hmap
);
279 CloseHandle(assembly
->hfile
);
281 free(assembly
->metadatahdr
);
282 free(assembly
->path
);
288 HRESULT
assembly_get_runtime_version(ASSEMBLY
*assembly
, LPSTR
*version
)
290 *version
= assembly
->metadatahdr
->Version
;
295 HRESULT
assembly_get_vtable_fixups(ASSEMBLY
*assembly
, VTableFixup
**fixups
, DWORD
*count
)
299 size
= assembly_datadir_get_data(assembly
, &assembly
->corhdr
->VTableFixups
, (void**)fixups
);
300 *count
= size
/ sizeof(VTableFixup
);
305 HRESULT
assembly_get_native_entrypoint(ASSEMBLY
*assembly
, NativeEntryPointFunc
*func
)
307 if (assembly
->corhdr
->Flags
& COMIMAGE_FLAGS_NATIVE_ENTRYPOINT
)
309 *func
= assembly_rva_to_va(assembly
, assembly
->corhdr
->u
.EntryPointRVA
);