Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenassembly.c
Go to the documentation of this file.
00001 /* 00002 * assembly parser 00003 * 00004 * Copyright 2008 James Hawkins 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include <stdarg.h> 00022 #include <stdio.h> 00023 00024 #include "windef.h" 00025 #include "winbase.h" 00026 #include "winuser.h" 00027 #include "winver.h" 00028 #include "wincrypt.h" 00029 #include "dbghelp.h" 00030 #include "ole2.h" 00031 #include "fusion.h" 00032 #include "corhdr.h" 00033 00034 #include "fusionpriv.h" 00035 #include "wine/debug.h" 00036 #include "wine/unicode.h" 00037 00038 #define TableFromToken(tk) (TypeFromToken(tk) >> 24) 00039 #define TokenFromTable(idx) (idx << 24) 00040 00041 #define MAX_CLR_TABLES 64 00042 00043 #define MD_STRINGS_BIT 0x1 00044 #define MD_GUIDS_BIT 0x2 00045 #define MD_BLOBS_BIT 0x4 00046 00047 typedef struct tagCLRTABLE 00048 { 00049 INT rows; 00050 DWORD offset; 00051 } CLRTABLE; 00052 00053 struct tagASSEMBLY 00054 { 00055 LPWSTR path; 00056 00057 HANDLE hfile; 00058 HANDLE hmap; 00059 BYTE *data; 00060 00061 IMAGE_NT_HEADERS *nthdr; 00062 IMAGE_COR20_HEADER *corhdr; 00063 00064 METADATAHDR *metadatahdr; 00065 00066 METADATATABLESHDR *tableshdr; 00067 DWORD numtables; 00068 DWORD *numrows; 00069 CLRTABLE tables[MAX_CLR_TABLES]; 00070 00071 DWORD stringsz; 00072 DWORD guidsz; 00073 DWORD blobsz; 00074 00075 BYTE *strings; 00076 BYTE *blobs; 00077 }; 00078 00079 static DWORD rva_to_offset(IMAGE_NT_HEADERS *nthdrs, DWORD rva) 00080 { 00081 DWORD offset = rva, limit; 00082 IMAGE_SECTION_HEADER *img; 00083 WORD i; 00084 00085 img = IMAGE_FIRST_SECTION(nthdrs); 00086 00087 if (rva < img->PointerToRawData) 00088 return rva; 00089 00090 for (i = 0; i < nthdrs->FileHeader.NumberOfSections; i++) 00091 { 00092 if (img[i].SizeOfRawData) 00093 limit = img[i].SizeOfRawData; 00094 else 00095 limit = img[i].Misc.VirtualSize; 00096 00097 if (rva >= img[i].VirtualAddress && 00098 rva < (img[i].VirtualAddress + limit)) 00099 { 00100 if (img[i].PointerToRawData != 0) 00101 { 00102 offset -= img[i].VirtualAddress; 00103 offset += img[i].PointerToRawData; 00104 } 00105 00106 return offset; 00107 } 00108 } 00109 00110 return 0; 00111 } 00112 00113 static BYTE *GetData(BYTE *pData, ULONG *pLength) 00114 { 00115 if ((*pData & 0x80) == 0x00) 00116 { 00117 *pLength = (*pData & 0x7f); 00118 return pData + 1; 00119 } 00120 00121 if ((*pData & 0xC0) == 0x80) 00122 { 00123 *pLength = ((*pData & 0x3f) << 8 | *(pData + 1)); 00124 return pData + 2; 00125 } 00126 00127 if ((*pData & 0xE0) == 0xC0) 00128 { 00129 *pLength = ((*pData & 0x1f) << 24 | *(pData + 1) << 16 | 00130 *(pData + 2) << 8 | *(pData + 3)); 00131 return pData + 4; 00132 } 00133 00134 *pLength = (ULONG)-1; 00135 return 0; 00136 } 00137 00138 static VOID *assembly_data_offset(ASSEMBLY *assembly, ULONG offset) 00139 { 00140 return &assembly->data[offset]; 00141 } 00142 00143 #define MAX_TABLES_WORD 0xFFFF 00144 #define MAX_TABLES_1BIT_ENCODE 32767 00145 #define MAX_TABLES_2BIT_ENCODE 16383 00146 #define MAX_TABLES_3BIT_ENCODE 8191 00147 #define MAX_TABLES_5BIT_ENCODE 2047 00148 00149 static inline ULONG get_table_size(const ASSEMBLY *assembly, DWORD index) 00150 { 00151 DWORD size; 00152 INT tables; 00153 00154 switch (TokenFromTable(index)) 00155 { 00156 case mdtModule: 00157 { 00158 size = sizeof(MODULETABLE) + (assembly->stringsz - sizeof(WORD)) + 00159 2 * (assembly->guidsz - sizeof(WORD)); 00160 break; 00161 } 00162 case mdtTypeRef: 00163 { 00164 size = sizeof(TYPEREFTABLE) + 2 * (assembly->stringsz - sizeof(WORD)); 00165 00166 /* ResolutionScope:ResolutionScope */ 00167 tables = max(assembly->tables[TableFromToken(mdtModule)].rows, 00168 assembly->tables[TableFromToken(mdtModuleRef)].rows); 00169 tables = max(tables, assembly->tables[TableFromToken(mdtAssemblyRef)].rows); 00170 tables = max(tables, assembly->tables[TableFromToken(mdtTypeRef)].rows); 00171 size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0; 00172 break; 00173 } 00174 case mdtTypeDef: 00175 { 00176 size = sizeof(TYPEDEFTABLE) + 2 * (assembly->stringsz - sizeof(WORD)); 00177 00178 /* Extends:TypeDefOrRef */ 00179 tables = max(assembly->tables[TableFromToken(mdtTypeDef)].rows, 00180 assembly->tables[TableFromToken(mdtTypeRef)].rows); 00181 tables = max(tables, assembly->tables[TableFromToken(mdtTypeSpec)].rows); 00182 size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0; 00183 00184 size += (assembly->tables[TableFromToken(mdtFieldDef)].rows > 00185 MAX_TABLES_WORD) ? sizeof(WORD) : 0; 00186 size += (assembly->tables[TableFromToken(mdtMethodDef)].rows > 00187 MAX_TABLES_WORD) ? sizeof(WORD) : 0; 00188 break; 00189 } 00190 case mdtFieldDef: 00191 { 00192 size = sizeof(FIELDTABLE) + (assembly->stringsz - sizeof(WORD)) + 00193 (assembly->blobsz - sizeof(WORD)); 00194 break; 00195 } 00196 case mdtMethodDef: 00197 { 00198 size = sizeof(METHODDEFTABLE) + (assembly->stringsz - sizeof(WORD)) + 00199 (assembly->blobsz - sizeof(WORD)); 00200 00201 size += (assembly->tables[TableFromToken(mdtParamDef)].rows > 00202 MAX_TABLES_WORD) ? sizeof(WORD) : 0; 00203 break; 00204 } 00205 case mdtParamDef: 00206 { 00207 size = sizeof(PARAMTABLE) + (assembly->stringsz - sizeof(WORD)); 00208 break; 00209 } 00210 case mdtInterfaceImpl: 00211 { 00212 size = sizeof(INTERFACEIMPLTABLE); 00213 00214 /* Interface:TypeDefOrRef */ 00215 tables = max(assembly->tables[TableFromToken(mdtTypeDef)].rows, 00216 assembly->tables[TableFromToken(mdtTypeRef)].rows); 00217 tables = max(tables, assembly->tables[TableFromToken(mdtTypeSpec)].rows); 00218 size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0; 00219 break; 00220 } 00221 case mdtMemberRef: 00222 { 00223 size = sizeof(MEMBERREFTABLE) + (assembly->stringsz - sizeof(WORD)) + 00224 (assembly->blobsz - sizeof(WORD)); 00225 00226 /* Class:MemberRefParent */ 00227 tables = max(assembly->tables[TableFromToken(mdtTypeRef)].rows, 00228 assembly->tables[TableFromToken(mdtModuleRef)].rows); 00229 tables = max(tables, assembly->tables[TableFromToken(mdtMethodDef)].rows); 00230 tables = max(tables, assembly->tables[TableFromToken(mdtTypeSpec)].rows); 00231 tables = max(tables, assembly->tables[TableFromToken(mdtTypeDef)].rows); 00232 size += (tables > MAX_TABLES_3BIT_ENCODE) ? sizeof(WORD) : 0; 00233 break; 00234 } 00235 case 0x0B000000: /* FIXME */ 00236 { 00237 size = sizeof(CONSTANTTABLE) + (assembly->blobsz - sizeof(WORD)); 00238 00239 /* Parent:HasConstant */ 00240 tables = max(assembly->tables[TableFromToken(mdtParamDef)].rows, 00241 assembly->tables[TableFromToken(mdtFieldDef)].rows); 00242 tables = max(tables, assembly->tables[TableFromToken(mdtProperty)].rows); 00243 size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0; 00244 break; 00245 } 00246 case mdtCustomAttribute: 00247 { 00248 size = sizeof(CUSTOMATTRIBUTETABLE) + (assembly->blobsz - sizeof(WORD)); 00249 00250 /* Parent:HasCustomAttribute */ 00251 tables = max(assembly->tables[TableFromToken(mdtMethodDef)].rows, 00252 assembly->tables[TableFromToken(mdtFieldDef)].rows); 00253 tables = max(tables, assembly->tables[TableFromToken(mdtTypeRef)].rows); 00254 tables = max(tables, assembly->tables[TableFromToken(mdtTypeDef)].rows); 00255 tables = max(tables, assembly->tables[TableFromToken(mdtParamDef)].rows); 00256 tables = max(tables, assembly->tables[TableFromToken(mdtInterfaceImpl)].rows); 00257 tables = max(tables, assembly->tables[TableFromToken(mdtMemberRef)].rows); 00258 tables = max(tables, assembly->tables[TableFromToken(mdtPermission)].rows); 00259 tables = max(tables, assembly->tables[TableFromToken(mdtProperty)].rows); 00260 tables = max(tables, assembly->tables[TableFromToken(mdtEvent)].rows); 00261 tables = max(tables, assembly->tables[TableFromToken(mdtSignature)].rows); 00262 tables = max(tables, assembly->tables[TableFromToken(mdtModuleRef)].rows); 00263 tables = max(tables, assembly->tables[TableFromToken(mdtTypeSpec)].rows); 00264 tables = max(tables, assembly->tables[TableFromToken(mdtAssembly)].rows); 00265 tables = max(tables, assembly->tables[TableFromToken(mdtFile)].rows); 00266 tables = max(tables, assembly->tables[TableFromToken(mdtExportedType)].rows); 00267 tables = max(tables, assembly->tables[TableFromToken(mdtManifestResource)].rows); 00268 size += (tables > MAX_TABLES_5BIT_ENCODE) ? sizeof(WORD) : 0; 00269 00270 /* Type:CustomAttributeType */ 00271 tables = max(assembly->tables[TableFromToken(mdtMethodDef)].rows, 00272 assembly->tables[TableFromToken(mdtMemberRef)].rows); 00273 size += (tables > MAX_TABLES_3BIT_ENCODE) ? sizeof(WORD) : 0; 00274 break; 00275 } 00276 case 0x0D000000: /* FIXME */ 00277 { 00278 size = sizeof(FIELDMARSHALTABLE) + (assembly->blobsz - sizeof(WORD)); 00279 00280 /* Parent:HasFieldMarshal */ 00281 tables = max(assembly->tables[TableFromToken(mdtFieldDef)].rows, 00282 assembly->tables[TableFromToken(mdtParamDef)].rows); 00283 size += (tables > MAX_TABLES_1BIT_ENCODE) ? sizeof(WORD) : 0; 00284 break; 00285 } 00286 case mdtPermission: 00287 { 00288 size = sizeof(DECLSECURITYTABLE) + (assembly->blobsz - sizeof(WORD)); 00289 00290 /* Parent:HasDeclSecurity */ 00291 tables = max(assembly->tables[TableFromToken(mdtTypeDef)].rows, 00292 assembly->tables[TableFromToken(mdtMethodDef)].rows); 00293 tables = max(tables, assembly->tables[TableFromToken(mdtAssembly)].rows); 00294 size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0; 00295 break; 00296 } 00297 case 0x0F000000: /* FIXME */ 00298 { 00299 size = sizeof(CLASSLAYOUTTABLE); 00300 size += (assembly->tables[TableFromToken(mdtTypeDef)].rows > 00301 MAX_TABLES_WORD) ? sizeof(WORD) : 0; 00302 break; 00303 } 00304 case 0x10000000: /* FIXME */ 00305 { 00306 size = sizeof(FIELDLAYOUTTABLE); 00307 size += (assembly->tables[TableFromToken(mdtFieldDef)].rows > 00308 MAX_TABLES_WORD) ? sizeof(WORD) : 0; 00309 break; 00310 } 00311 case mdtSignature: 00312 { 00313 size = sizeof(STANDALONESIGTABLE) + (assembly->blobsz - sizeof(WORD)); 00314 break; 00315 } 00316 case 0x12000000: /* FIXME */ 00317 { 00318 size = sizeof(EVENTMAPTABLE); 00319 size += (assembly->tables[TableFromToken(mdtTypeDef)].rows > 00320 MAX_TABLES_WORD) ? sizeof(WORD) : 0; 00321 size += (assembly->tables[TableFromToken(mdtEvent)].rows > 00322 MAX_TABLES_WORD) ? sizeof(WORD) : 0; 00323 break; 00324 } 00325 case mdtEvent: 00326 { 00327 size = sizeof(EVENTTABLE) + (assembly->stringsz - sizeof(WORD)); 00328 00329 /* EventType:TypeDefOrRef */ 00330 tables = max(assembly->tables[TableFromToken(mdtTypeDef)].rows, 00331 assembly->tables[TableFromToken(mdtTypeRef)].rows); 00332 tables = max(tables, assembly->tables[TableFromToken(mdtTypeSpec)].rows); 00333 size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0; 00334 break; 00335 } 00336 case 0x15000000:/* FIXME */ 00337 { 00338 size = sizeof(PROPERTYMAPTABLE); 00339 size += (assembly->tables[TableFromToken(mdtTypeDef)].rows > 00340 MAX_TABLES_WORD) ? sizeof(WORD) : 0; 00341 size += (assembly->tables[TableFromToken(mdtProperty)].rows > 00342 MAX_TABLES_WORD) ? sizeof(WORD) : 0; 00343 break; 00344 } 00345 case mdtProperty: 00346 { 00347 size = sizeof(PROPERTYTABLE) + (assembly->stringsz - sizeof(WORD)) + 00348 (assembly->blobsz - sizeof(WORD)); 00349 break; 00350 } 00351 case 0x18000000: /* FIXME */ 00352 { 00353 size = sizeof(METHODSEMANTICSTABLE); 00354 00355 /* Association:HasSemantics */ 00356 tables = max(assembly->tables[TableFromToken(mdtEvent)].rows, 00357 assembly->tables[TableFromToken(mdtProperty)].rows); 00358 size += (tables > MAX_TABLES_1BIT_ENCODE) ? sizeof(WORD) : 0; 00359 00360 size += (assembly->tables[TableFromToken(mdtMethodDef)].rows > 00361 MAX_TABLES_WORD) ? sizeof(WORD) : 0; 00362 break; 00363 } 00364 case 0x19000000: /* FIXME */ 00365 { 00366 size = sizeof(METHODIMPLTABLE); 00367 00368 /* MethodBody:MethodDefOrRef, MethodDeclaration:MethodDefOrRef */ 00369 tables = max(assembly->tables[TableFromToken(mdtMethodDef)].rows, 00370 assembly->tables[TableFromToken(mdtMemberRef)].rows); 00371 size += (tables > MAX_TABLES_1BIT_ENCODE) ? 2 * sizeof(WORD) : 0; 00372 00373 size += (assembly->tables[TableFromToken(mdtTypeDef)].rows > 00374 MAX_TABLES_WORD) ? sizeof(WORD) : 0; 00375 break; 00376 } 00377 case mdtModuleRef: 00378 { 00379 size = sizeof(MODULEREFTABLE) + (assembly->stringsz - sizeof(WORD)); 00380 break; 00381 } 00382 case mdtTypeSpec: 00383 { 00384 size = sizeof(TYPESPECTABLE) + (assembly->blobsz - sizeof(WORD)); 00385 break; 00386 } 00387 case 0x1C000000: /* FIXME */ 00388 { 00389 size = sizeof(IMPLMAPTABLE) + (assembly->stringsz - sizeof(WORD)); 00390 00391 /* MemberForwarded:MemberForwarded */ 00392 tables = max(assembly->tables[TableFromToken(mdtFieldDef)].rows, 00393 assembly->tables[TableFromToken(mdtMethodDef)].rows); 00394 size += (tables > MAX_TABLES_1BIT_ENCODE) ? sizeof(WORD) : 0; 00395 00396 size += (assembly->tables[TableFromToken(mdtModuleRef)].rows > 00397 MAX_TABLES_WORD) ? sizeof(WORD) : 0; 00398 break; 00399 } 00400 case 0x1D000000: /* FIXME */ 00401 { 00402 size = sizeof(FIELDRVATABLE); 00403 size += (assembly->tables[TableFromToken(mdtFieldDef)].rows > 00404 MAX_TABLES_WORD) ? sizeof(WORD) : 0; 00405 break; 00406 } 00407 case mdtAssembly: 00408 { 00409 size = sizeof(ASSEMBLYTABLE) + 2 * (assembly->stringsz - sizeof(WORD)) + 00410 (assembly->blobsz - sizeof(WORD)); 00411 break; 00412 } 00413 case 0x20000001: /* FIXME */ 00414 { 00415 size = sizeof(ASSEMBLYPROCESSORTABLE); 00416 break; 00417 } 00418 case 0x22000000: /* FIXME */ 00419 { 00420 size = sizeof(ASSEMBLYOSTABLE); 00421 break; 00422 } 00423 case mdtAssemblyRef: 00424 { 00425 size = sizeof(ASSEMBLYREFTABLE) + 2 * (assembly->stringsz - sizeof(WORD)) + 00426 2 * (assembly->blobsz - sizeof(WORD)); 00427 break; 00428 } 00429 case 0x24000000: /* FIXME */ 00430 { 00431 size = sizeof(ASSEMBLYREFPROCESSORTABLE); 00432 size += (assembly->tables[TableFromToken(mdtAssemblyRef)].rows > 00433 MAX_TABLES_WORD) ? sizeof(WORD) : 0; 00434 break; 00435 } 00436 case 0x25000000: /* FIXME */ 00437 { 00438 size = sizeof(ASSEMBLYREFOSTABLE); 00439 size += (assembly->tables[TableFromToken(mdtAssemblyRef)].rows > 00440 MAX_TABLES_WORD) ? sizeof(WORD) : 0; 00441 break; 00442 } 00443 case mdtFile: 00444 { 00445 size = sizeof(FILETABLE) + (assembly->stringsz - sizeof(WORD)) + 00446 (assembly->blobsz - sizeof(WORD)); 00447 break; 00448 } 00449 case mdtExportedType: 00450 { 00451 size = sizeof(EXPORTEDTYPETABLE) + 2 * (assembly->stringsz - sizeof(WORD)); 00452 00453 /* Implementation:Implementation */ 00454 tables = max(assembly->tables[TableFromToken(mdtFile)].rows, 00455 assembly->tables[TableFromToken(mdtMethodDef)].rows); 00456 size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0; 00457 break; 00458 } 00459 case mdtManifestResource: 00460 { 00461 size = sizeof(MANIFESTRESTABLE) + (assembly->stringsz - sizeof(WORD)); 00462 00463 /* Implementation:Implementation */ 00464 tables = max(assembly->tables[TableFromToken(mdtFile)].rows, 00465 assembly->tables[TableFromToken(mdtAssemblyRef)].rows); 00466 size += (tables > MAX_TABLES_2BIT_ENCODE) ? sizeof(WORD) : 0; 00467 break; 00468 } 00469 case 0x29000000: /* FIXME */ 00470 { 00471 size = sizeof(NESTEDCLASSTABLE); 00472 size += (assembly->tables[TableFromToken(mdtTypeDef)].rows > 00473 MAX_TABLES_WORD) ? 2 * sizeof(WORD) : 0; 00474 break; 00475 } 00476 default: 00477 return 0; 00478 } 00479 00480 return size; 00481 } 00482 00483 static HRESULT parse_clr_tables(ASSEMBLY *assembly, ULONG offset) 00484 { 00485 DWORD i, previ, offidx; 00486 ULONG currofs; 00487 00488 currofs = offset; 00489 assembly->tableshdr = assembly_data_offset(assembly, currofs); 00490 if (!assembly->tableshdr) 00491 return E_FAIL; 00492 00493 assembly->stringsz = (assembly->tableshdr->HeapOffsetSizes & MD_STRINGS_BIT) ? 00494 sizeof(DWORD) : sizeof(WORD); 00495 assembly->guidsz = (assembly->tableshdr->HeapOffsetSizes & MD_GUIDS_BIT) ? 00496 sizeof(DWORD) : sizeof(WORD); 00497 assembly->blobsz = (assembly->tableshdr->HeapOffsetSizes & MD_BLOBS_BIT) ? 00498 sizeof(DWORD) : sizeof(WORD); 00499 00500 currofs += sizeof(METADATATABLESHDR); 00501 assembly->numrows = assembly_data_offset(assembly, currofs); 00502 if (!assembly->numrows) 00503 return E_FAIL; 00504 00505 assembly->numtables = 0; 00506 for (i = 0; i < MAX_CLR_TABLES; i++) 00507 { 00508 if ((i < 32 && (assembly->tableshdr->MaskValid.u.LowPart >> i) & 1) || 00509 (i >= 32 && (assembly->tableshdr->MaskValid.u.HighPart >> i) & 1)) 00510 { 00511 assembly->numtables++; 00512 } 00513 } 00514 00515 currofs += assembly->numtables * sizeof(DWORD); 00516 memset(assembly->tables, -1, MAX_CLR_TABLES * sizeof(CLRTABLE)); 00517 00518 if (assembly->tableshdr->MaskValid.u.LowPart & 1) 00519 assembly->tables[0].offset = currofs; 00520 00521 offidx = 0; 00522 for (i = 0; i < MAX_CLR_TABLES; i++) 00523 { 00524 if ((i < 32 && (assembly->tableshdr->MaskValid.u.LowPart >> i) & 1) || 00525 (i >= 32 && (assembly->tableshdr->MaskValid.u.HighPart >> i) & 1)) 00526 { 00527 assembly->tables[i].rows = assembly->numrows[offidx]; 00528 offidx++; 00529 } 00530 } 00531 00532 previ = 0; 00533 offidx = 1; 00534 for (i = 1; i < MAX_CLR_TABLES; i++) 00535 { 00536 if ((i < 32 && (assembly->tableshdr->MaskValid.u.LowPart >> i) & 1) || 00537 (i >= 32 && (assembly->tableshdr->MaskValid.u.HighPart >> i) & 1)) 00538 { 00539 currofs += get_table_size(assembly, previ) * assembly->numrows[offidx - 1]; 00540 assembly->tables[i].offset = currofs; 00541 offidx++; 00542 previ = i; 00543 } 00544 } 00545 00546 return S_OK; 00547 } 00548 00549 static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz) 00550 { 00551 METADATAHDR *metadatahdr; 00552 BYTE *ptr, *dest; 00553 DWORD size, ofs; 00554 ULONG rva; 00555 00556 rva = assembly->corhdr->MetaData.VirtualAddress; 00557 ptr = ImageRvaToVa(assembly->nthdr, assembly->data, rva, NULL); 00558 if (!ptr) 00559 return E_FAIL; 00560 00561 metadatahdr = (METADATAHDR *)ptr; 00562 00563 assembly->metadatahdr = HeapAlloc(GetProcessHeap(), 0, sizeof(METADATAHDR)); 00564 if (!assembly->metadatahdr) 00565 return E_OUTOFMEMORY; 00566 00567 size = FIELD_OFFSET(METADATAHDR, Version); 00568 memcpy(assembly->metadatahdr, metadatahdr, size); 00569 00570 /* we don't care about the version string */ 00571 00572 ofs = FIELD_OFFSET(METADATAHDR, Flags); 00573 ptr += FIELD_OFFSET(METADATAHDR, Version) + metadatahdr->VersionLength + 1; 00574 dest = (BYTE *)assembly->metadatahdr + ofs; 00575 memcpy(dest, ptr, sizeof(METADATAHDR) - ofs); 00576 00577 *hdrsz = sizeof(METADATAHDR) - sizeof(LPSTR) + metadatahdr->VersionLength + 1; 00578 00579 return S_OK; 00580 } 00581 00582 static HRESULT parse_clr_metadata(ASSEMBLY *assembly) 00583 { 00584 METADATASTREAMHDR *streamhdr; 00585 ULONG rva, i, ofs; 00586 LPSTR stream; 00587 HRESULT hr; 00588 DWORD hdrsz; 00589 BYTE *ptr; 00590 00591 hr = parse_metadata_header(assembly, &hdrsz); 00592 if (FAILED(hr)) 00593 return hr; 00594 00595 rva = assembly->corhdr->MetaData.VirtualAddress; 00596 ptr = ImageRvaToVa(assembly->nthdr, assembly->data, rva + hdrsz, NULL); 00597 if (!ptr) 00598 return E_FAIL; 00599 00600 for (i = 0; i < assembly->metadatahdr->Streams; i++) 00601 { 00602 streamhdr = (METADATASTREAMHDR *)ptr; 00603 ofs = rva_to_offset(assembly->nthdr, rva + streamhdr->Offset); 00604 00605 ptr += sizeof(METADATASTREAMHDR); 00606 stream = (LPSTR)ptr; 00607 00608 if (!lstrcmpA(stream, "#~")) 00609 { 00610 hr = parse_clr_tables(assembly, ofs); 00611 if (FAILED(hr)) 00612 return hr; 00613 } 00614 else if (!lstrcmpA(stream, "#Strings") || !lstrcmpA(stream, "Strings")) 00615 assembly->strings = assembly_data_offset(assembly, ofs); 00616 else if (!lstrcmpA(stream, "#Blob") || !lstrcmpA(stream, "Blob")) 00617 assembly->blobs = assembly_data_offset(assembly, ofs); 00618 00619 ptr += lstrlenA(stream) + 1; 00620 ptr = (BYTE *)(((UINT_PTR)ptr + 3) & ~3); /* align on DWORD boundary */ 00621 } 00622 00623 return S_OK; 00624 } 00625 00626 static HRESULT parse_pe_header(ASSEMBLY *assembly) 00627 { 00628 IMAGE_DATA_DIRECTORY *datadirs; 00629 00630 assembly->nthdr = ImageNtHeader(assembly->data); 00631 if (!assembly->nthdr) 00632 return E_FAIL; 00633 00634 if (assembly->nthdr->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) 00635 { 00636 IMAGE_OPTIONAL_HEADER64 *opthdr = 00637 (IMAGE_OPTIONAL_HEADER64 *)&assembly->nthdr->OptionalHeader; 00638 datadirs = opthdr->DataDirectory; 00639 } 00640 else 00641 { 00642 IMAGE_OPTIONAL_HEADER32 *opthdr = 00643 (IMAGE_OPTIONAL_HEADER32 *)&assembly->nthdr->OptionalHeader; 00644 datadirs = opthdr->DataDirectory; 00645 } 00646 00647 if (!datadirs) 00648 return E_FAIL; 00649 00650 if (!datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress || 00651 !datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size) 00652 { 00653 return E_FAIL; 00654 } 00655 00656 assembly->corhdr = ImageRvaToVa(assembly->nthdr, assembly->data, 00657 datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress, NULL); 00658 if (!assembly->corhdr) 00659 return E_FAIL; 00660 00661 return S_OK; 00662 } 00663 00664 HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) 00665 { 00666 ASSEMBLY *assembly; 00667 HRESULT hr; 00668 00669 *out = NULL; 00670 00671 assembly = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ASSEMBLY)); 00672 if (!assembly) 00673 return E_OUTOFMEMORY; 00674 00675 assembly->path = strdupW(file); 00676 if (!assembly->path) 00677 { 00678 hr = E_OUTOFMEMORY; 00679 goto failed; 00680 } 00681 00682 assembly->hfile = CreateFileW(file, GENERIC_READ, FILE_SHARE_READ, 00683 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 00684 if (assembly->hfile == INVALID_HANDLE_VALUE) 00685 { 00686 hr = HRESULT_FROM_WIN32(GetLastError()); 00687 goto failed; 00688 } 00689 00690 assembly->hmap = CreateFileMappingW(assembly->hfile, NULL, PAGE_READONLY, 00691 0, 0, NULL); 00692 if (!assembly->hmap) 00693 { 00694 hr = HRESULT_FROM_WIN32(GetLastError()); 00695 goto failed; 00696 } 00697 00698 assembly->data = MapViewOfFile(assembly->hmap, FILE_MAP_READ, 0, 0, 0); 00699 if (!assembly->data) 00700 { 00701 hr = HRESULT_FROM_WIN32(GetLastError()); 00702 goto failed; 00703 } 00704 00705 hr = parse_pe_header(assembly); 00706 if (FAILED(hr)) goto failed; 00707 00708 hr = parse_clr_metadata(assembly); 00709 if (FAILED(hr)) goto failed; 00710 00711 *out = assembly; 00712 return S_OK; 00713 00714 failed: 00715 assembly_release(assembly); 00716 return hr; 00717 } 00718 00719 HRESULT assembly_release(ASSEMBLY *assembly) 00720 { 00721 if (!assembly) 00722 return S_OK; 00723 00724 HeapFree(GetProcessHeap(), 0, assembly->metadatahdr); 00725 HeapFree(GetProcessHeap(), 0, assembly->path); 00726 UnmapViewOfFile(assembly->data); 00727 CloseHandle(assembly->hmap); 00728 CloseHandle(assembly->hfile); 00729 HeapFree(GetProcessHeap(), 0, assembly); 00730 00731 return S_OK; 00732 } 00733 00734 static LPWSTR assembly_dup_str(const ASSEMBLY *assembly, DWORD index) 00735 { 00736 int len; 00737 LPWSTR cpy; 00738 LPCSTR str = (LPCSTR)&assembly->strings[index]; 00739 00740 len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); 00741 00742 if ((cpy = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) 00743 MultiByteToWideChar(CP_ACP, 0, str, -1, cpy, len); 00744 00745 return cpy; 00746 } 00747 00748 HRESULT assembly_get_name(ASSEMBLY *assembly, LPWSTR *name) 00749 { 00750 BYTE *ptr; 00751 LONG offset; 00752 DWORD stridx; 00753 00754 offset = assembly->tables[TableFromToken(mdtAssembly)].offset; 00755 if (offset == -1) 00756 return E_FAIL; 00757 00758 ptr = assembly_data_offset(assembly, offset); 00759 if (!ptr) 00760 return E_FAIL; 00761 00762 ptr += FIELD_OFFSET(ASSEMBLYTABLE, PublicKey) + assembly->blobsz; 00763 if (assembly->stringsz == sizeof(DWORD)) 00764 stridx = *((DWORD *)ptr); 00765 else 00766 stridx = *((WORD *)ptr); 00767 00768 *name = assembly_dup_str(assembly, stridx); 00769 if (!*name) 00770 return E_OUTOFMEMORY; 00771 00772 return S_OK; 00773 } 00774 00775 HRESULT assembly_get_path(const ASSEMBLY *assembly, LPWSTR *path) 00776 { 00777 LPWSTR cpy = HeapAlloc(GetProcessHeap(), 0, (strlenW(assembly->path) + 1) * sizeof(WCHAR)); 00778 *path = cpy; 00779 if (cpy) 00780 strcpyW(cpy, assembly->path); 00781 else 00782 return E_OUTOFMEMORY; 00783 00784 return S_OK; 00785 } 00786 00787 HRESULT assembly_get_version(ASSEMBLY *assembly, LPWSTR *version) 00788 { 00789 static const WCHAR format[] = {'%','u','.','%','u','.','%','u','.','%','u',0}; 00790 00791 ASSEMBLYTABLE *asmtbl; 00792 LONG offset; 00793 00794 *version = NULL; 00795 00796 offset = assembly->tables[TableFromToken(mdtAssembly)].offset; 00797 if (offset == -1) 00798 return E_FAIL; 00799 00800 asmtbl = assembly_data_offset(assembly, offset); 00801 if (!asmtbl) 00802 return E_FAIL; 00803 00804 *version = HeapAlloc(GetProcessHeap(), 0, sizeof(format) + 4 * strlen("65535") * sizeof(WCHAR)); 00805 if (!*version) 00806 return E_OUTOFMEMORY; 00807 00808 sprintfW(*version, format, asmtbl->MajorVersion, asmtbl->MinorVersion, 00809 asmtbl->BuildNumber, asmtbl->RevisionNumber); 00810 00811 return S_OK; 00812 } 00813 00814 BYTE assembly_get_architecture(ASSEMBLY *assembly) 00815 { 00816 if ((assembly->corhdr->MajorRuntimeVersion == 2) && (assembly->corhdr->MinorRuntimeVersion == 0)) 00817 return 0; /* .NET 1.x assembly */ 00818 00819 if (assembly->nthdr->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) 00820 return peAMD64; /* AMD64/IA64 assembly */ 00821 00822 if ((assembly->corhdr->Flags & COMIMAGE_FLAGS_ILONLY) && !(assembly->corhdr->Flags & COMIMAGE_FLAGS_32BITREQUIRED)) 00823 return peMSIL; /* MSIL assembly */ 00824 00825 return peI386; /* x86 assembly */ 00826 } 00827 00828 static BYTE *assembly_get_blob(ASSEMBLY *assembly, WORD index, ULONG *size) 00829 { 00830 return GetData(&assembly->blobs[index], size); 00831 } 00832 00833 HRESULT assembly_get_pubkey_token(ASSEMBLY *assembly, LPWSTR *token) 00834 { 00835 ASSEMBLYTABLE *asmtbl; 00836 ULONG i, size; 00837 LONG offset; 00838 BYTE *hashdata; 00839 HCRYPTPROV crypt; 00840 HCRYPTHASH hash; 00841 BYTE *pubkey; 00842 BYTE tokbytes[BYTES_PER_TOKEN]; 00843 HRESULT hr = E_FAIL; 00844 LPWSTR tok; 00845 00846 *token = NULL; 00847 00848 offset = assembly->tables[TableFromToken(mdtAssembly)].offset; 00849 if (offset == -1) 00850 return E_FAIL; 00851 00852 asmtbl = assembly_data_offset(assembly, offset); 00853 if (!asmtbl) 00854 return E_FAIL; 00855 00856 pubkey = assembly_get_blob(assembly, asmtbl->PublicKey, &size); 00857 00858 if (!CryptAcquireContextA(&crypt, NULL, NULL, PROV_RSA_FULL, 00859 CRYPT_VERIFYCONTEXT)) 00860 return E_FAIL; 00861 00862 if (!CryptCreateHash(crypt, CALG_SHA1, 0, 0, &hash)) 00863 return E_FAIL; 00864 00865 if (!CryptHashData(hash, pubkey, size, 0)) 00866 return E_FAIL; 00867 00868 size = 0; 00869 if (!CryptGetHashParam(hash, HP_HASHVAL, NULL, &size, 0)) 00870 return E_FAIL; 00871 00872 hashdata = HeapAlloc(GetProcessHeap(), 0, size); 00873 if (!hashdata) 00874 { 00875 hr = E_OUTOFMEMORY; 00876 goto done; 00877 } 00878 00879 if (!CryptGetHashParam(hash, HP_HASHVAL, hashdata, &size, 0)) 00880 goto done; 00881 00882 for (i = size - 1; i >= size - 8; i--) 00883 tokbytes[size - i - 1] = hashdata[i]; 00884 00885 tok = HeapAlloc(GetProcessHeap(), 0, (TOKEN_LENGTH + 1) * sizeof(WCHAR)); 00886 if (!tok) 00887 { 00888 hr = E_OUTOFMEMORY; 00889 goto done; 00890 } 00891 00892 token_to_str(tokbytes, tok); 00893 00894 *token = tok; 00895 hr = S_OK; 00896 00897 done: 00898 HeapFree(GetProcessHeap(), 0, hashdata); 00899 CryptDestroyHash(hash); 00900 CryptReleaseContext(crypt, 0); 00901 00902 return hr; 00903 } Generated on Fri May 25 2012 04:21:37 for ReactOS by
1.7.6.1
|