ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

assembly.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.