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

resource.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of VERSION.DLL - Resource Access routines
00003  *
00004  * Copyright 1996,1997 Marcus Meissner
00005  * Copyright 1997 David Cuthbert
00006  * Copyright 1999 Ulrich Weigand
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00021  */
00022 
00023 #include "config.h"
00024 
00025 #include <stdarg.h>
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <sys/types.h>
00030 #ifdef HAVE_UNISTD_H
00031 # include <unistd.h>
00032 #endif
00033 
00034 #define NONAMELESSUNION
00035 #define NONAMELESSSTRUCT
00036 #include "windef.h"
00037 #include "winbase.h"
00038 #include "lzexpand.h"
00039 #include "winuser.h"
00040 #include "winver.h"
00041 #undef VS_FILE_INFO
00042 #define VS_FILE_INFO 16
00043 
00044 #include "wine/unicode.h"
00045 
00046 #include "wine/debug.h"
00047 
00048 typedef struct
00049 {
00050     WORD offset;
00051     WORD length;
00052     WORD flags;
00053     WORD id;
00054     WORD handle;
00055     WORD usage;
00056 } NE_NAMEINFO;
00057 
00058 typedef struct
00059 {
00060     WORD  type_id;
00061     WORD  count;
00062     DWORD resloader;
00063 } NE_TYPEINFO;
00064 
00065 WINE_DEFAULT_DEBUG_CHANNEL(ver);
00066 
00067 
00068 /**********************************************************************
00069  *  find_entry_by_id
00070  *
00071  * Find an entry by id in a resource directory
00072  * Copied from loader/pe_resource.c
00073  */
00074 static const IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( const IMAGE_RESOURCE_DIRECTORY *dir,
00075                                                          WORD id, const void *root )
00076 {
00077     const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
00078     int min, max, pos;
00079 
00080     entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
00081     min = dir->NumberOfNamedEntries;
00082     max = min + dir->NumberOfIdEntries - 1;
00083     while (min <= max)
00084     {
00085         pos = (min + max) / 2;
00086         if (entry[pos].u1.Id == id)
00087             return (const IMAGE_RESOURCE_DIRECTORY *)((const char *)root + entry[pos].u2.s3.OffsetToDirectory);
00088         if (entry[pos].u1.Id > id) max = pos - 1;
00089         else min = pos + 1;
00090     }
00091     return NULL;
00092 }
00093 
00094 
00095 /**********************************************************************
00096  *  find_entry_default
00097  *
00098  * Find a default entry in a resource directory
00099  * Copied from loader/pe_resource.c
00100  */
00101 static const IMAGE_RESOURCE_DIRECTORY *find_entry_default( const IMAGE_RESOURCE_DIRECTORY *dir,
00102                                                            const void *root )
00103 {
00104     const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
00105 
00106     entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
00107     return (const IMAGE_RESOURCE_DIRECTORY *)((const char *)root + entry->u2.s3.OffsetToDirectory);
00108 }
00109 
00110 
00111 /***********************************************************************
00112  *           read_xx_header         [internal]
00113  */
00114 static int read_xx_header( HFILE lzfd )
00115 {
00116     IMAGE_DOS_HEADER mzh;
00117     char magic[3];
00118 
00119     LZSeek( lzfd, 0, SEEK_SET );
00120     if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
00121         return 0;
00122     if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
00123     {
00124         if (!memcmp( &mzh, "\177ELF", 4 )) return 1;  /* ELF */
00125         if (*(UINT *)&mzh == 0xfeedface || *(UINT *)&mzh == 0xcefaedfe) return 1;  /* Mach-O */
00126         return 0;
00127     }
00128 
00129     LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
00130     if ( 2 != LZRead( lzfd, magic, 2 ) )
00131         return 0;
00132 
00133     LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
00134 
00135     if ( magic[0] == 'N' && magic[1] == 'E' )
00136         return IMAGE_OS2_SIGNATURE;
00137     if ( magic[0] == 'P' && magic[1] == 'E' )
00138         return IMAGE_NT_SIGNATURE;
00139 
00140     magic[2] = '\0';
00141     WARN("Can't handle %s files.\n", magic );
00142     return 0;
00143 }
00144 
00145 /***********************************************************************
00146  *           find_ne_resource         [internal]
00147  */
00148 static BOOL find_ne_resource( HFILE lzfd, DWORD *resLen, DWORD *resOff )
00149 {
00150     const WORD typeid = VS_FILE_INFO | 0x8000;
00151     const WORD resid = VS_VERSION_INFO | 0x8000;
00152     IMAGE_OS2_HEADER nehd;
00153     NE_TYPEINFO *typeInfo;
00154     NE_NAMEINFO *nameInfo;
00155     DWORD nehdoffset;
00156     LPBYTE resTab;
00157     DWORD resTabSize;
00158     int count;
00159 
00160     /* Read in NE header */
00161     nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
00162     if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
00163 
00164     resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
00165     if ( !resTabSize )
00166     {
00167         TRACE("No resources in NE dll\n" );
00168         return FALSE;
00169     }
00170 
00171     /* Read in resource table */
00172     resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
00173     if ( !resTab ) return FALSE;
00174 
00175     LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
00176     if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
00177     {
00178         HeapFree( GetProcessHeap(), 0, resTab );
00179         return FALSE;
00180     }
00181 
00182     /* Find resource */
00183     typeInfo = (NE_TYPEINFO *)(resTab + 2);
00184     while (typeInfo->type_id)
00185     {
00186         if (typeInfo->type_id == typeid) goto found_type;
00187         typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
00188                                    typeInfo->count * sizeof(NE_NAMEINFO));
00189     }
00190     TRACE("No typeid entry found\n" );
00191     HeapFree( GetProcessHeap(), 0, resTab );
00192     return FALSE;
00193 
00194  found_type:
00195     nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
00196 
00197     for (count = typeInfo->count; count > 0; count--, nameInfo++)
00198         if (nameInfo->id == resid) goto found_name;
00199 
00200     TRACE("No resid entry found\n" );
00201     HeapFree( GetProcessHeap(), 0, resTab );
00202     return FALSE;
00203 
00204  found_name:
00205     /* Return resource data */
00206     if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
00207     if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
00208 
00209     HeapFree( GetProcessHeap(), 0, resTab );
00210     return TRUE;
00211 }
00212 
00213 /***********************************************************************
00214  *           find_pe_resource         [internal]
00215  */
00216 static BOOL find_pe_resource( HFILE lzfd, DWORD *resLen, DWORD *resOff )
00217 {
00218     union
00219     {
00220         IMAGE_NT_HEADERS32 nt32;
00221         IMAGE_NT_HEADERS64 nt64;
00222     } pehd;
00223     DWORD pehdoffset;
00224     PIMAGE_DATA_DIRECTORY resDataDir;
00225     PIMAGE_SECTION_HEADER sections;
00226     LPBYTE resSection;
00227     DWORD resSectionSize;
00228     const void *resDir;
00229     const IMAGE_RESOURCE_DIRECTORY *resPtr;
00230     const IMAGE_RESOURCE_DATA_ENTRY *resData;
00231     int i, len, nSections;
00232     BOOL ret = FALSE;
00233 
00234     /* Read in PE header */
00235     pehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
00236     len = LZRead( lzfd, (LPSTR)&pehd, sizeof(pehd) );
00237     if (len < sizeof(pehd.nt32.FileHeader)) return 0;
00238     if (len < sizeof(pehd)) memset( (char *)&pehd + len, 0, sizeof(pehd) - len );
00239 
00240     switch (pehd.nt32.OptionalHeader.Magic)
00241     {
00242     case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
00243         resDataDir = pehd.nt32.OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_RESOURCE;
00244         break;
00245     case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
00246         resDataDir = pehd.nt64.OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_RESOURCE;
00247         break;
00248     default:
00249         return 0;
00250     }
00251 
00252     if ( !resDataDir->Size )
00253     {
00254         TRACE("No resources in PE dll\n" );
00255         return FALSE;
00256     }
00257 
00258     /* Read in section table */
00259     nSections = pehd.nt32.FileHeader.NumberOfSections;
00260     sections = HeapAlloc( GetProcessHeap(), 0,
00261                           nSections * sizeof(IMAGE_SECTION_HEADER) );
00262     if ( !sections ) return FALSE;
00263 
00264     len = FIELD_OFFSET( IMAGE_NT_HEADERS32, OptionalHeader ) + pehd.nt32.FileHeader.SizeOfOptionalHeader;
00265     LZSeek( lzfd, pehdoffset + len, SEEK_SET );
00266 
00267     if ( nSections * sizeof(IMAGE_SECTION_HEADER) !=
00268          LZRead( lzfd, (LPSTR)sections, nSections * sizeof(IMAGE_SECTION_HEADER) ) )
00269     {
00270         HeapFree( GetProcessHeap(), 0, sections );
00271         return FALSE;
00272     }
00273 
00274     /* Find resource section */
00275     for ( i = 0; i < nSections; i++ )
00276         if (    resDataDir->VirtualAddress >= sections[i].VirtualAddress
00277              && resDataDir->VirtualAddress <  sections[i].VirtualAddress +
00278                                               sections[i].SizeOfRawData )
00279             break;
00280 
00281     if ( i == nSections )
00282     {
00283         HeapFree( GetProcessHeap(), 0, sections );
00284         TRACE("Couldn't find resource section\n" );
00285         return FALSE;
00286     }
00287 
00288     /* Read in resource section */
00289     resSectionSize = sections[i].SizeOfRawData;
00290     resSection = HeapAlloc( GetProcessHeap(), 0, resSectionSize );
00291     if ( !resSection )
00292     {
00293         HeapFree( GetProcessHeap(), 0, sections );
00294         return FALSE;
00295     }
00296 
00297     LZSeek( lzfd, sections[i].PointerToRawData, SEEK_SET );
00298     if ( resSectionSize != LZRead( lzfd, (char*)resSection, resSectionSize ) ) goto done;
00299 
00300     /* Find resource */
00301     resDir = resSection + (resDataDir->VirtualAddress - sections[i].VirtualAddress);
00302 
00303     resPtr = resDir;
00304     resPtr = find_entry_by_id( resPtr, VS_FILE_INFO, resDir );
00305     if ( !resPtr )
00306     {
00307         TRACE("No typeid entry found\n" );
00308         goto done;
00309     }
00310     resPtr = find_entry_by_id( resPtr, VS_VERSION_INFO, resDir );
00311     if ( !resPtr )
00312     {
00313         TRACE("No resid entry found\n" );
00314         goto done;
00315     }
00316     resPtr = find_entry_default( resPtr, resDir );
00317     if ( !resPtr )
00318     {
00319         TRACE("No default language entry found\n" );
00320         goto done;
00321     }
00322 
00323     /* Find resource data section */
00324     resData = (const IMAGE_RESOURCE_DATA_ENTRY*)resPtr;
00325     for ( i = 0; i < nSections; i++ )
00326         if (    resData->OffsetToData >= sections[i].VirtualAddress
00327              && resData->OffsetToData <  sections[i].VirtualAddress +
00328                                          sections[i].SizeOfRawData )
00329             break;
00330 
00331     if ( i == nSections )
00332     {
00333         TRACE("Couldn't find resource data section\n" );
00334         goto done;
00335     }
00336 
00337     /* Return resource data */
00338     if ( resLen ) *resLen = resData->Size;
00339     if ( resOff ) *resOff = resData->OffsetToData - sections[i].VirtualAddress
00340                             + sections[i].PointerToRawData;
00341     ret = TRUE;
00342 
00343  done:
00344     HeapFree( GetProcessHeap(), 0, resSection );
00345     HeapFree( GetProcessHeap(), 0, sections );
00346     return ret;
00347 }
00348 
00349 
00350 /***********************************************************************
00351  *           find_version_resource         [internal]
00352  */
00353 DWORD find_version_resource( HFILE lzfd, DWORD *reslen, DWORD *offset )
00354 {
00355     DWORD magic = read_xx_header( lzfd );
00356 
00357     switch (magic)
00358     {
00359     case IMAGE_OS2_SIGNATURE:
00360         if (!find_ne_resource( lzfd, reslen, offset )) magic = 0;
00361         break;
00362     case IMAGE_NT_SIGNATURE:
00363         if (!find_pe_resource( lzfd, reslen, offset )) magic = 0;
00364         break;
00365     }
00366     return magic;
00367 }

Generated on Sat May 26 2012 04:20:49 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.