2 * Implementation of VERSION.DLL - Resource Access routines
4 * Copyright 1996,1997 Marcus Meissner
5 * Copyright 1997 David Cuthbert
6 * Copyright 1999 Ulrich Weigand
19 #include "debugtools.h"
21 DEFAULT_DEBUG_CHANNEL(ver)
24 /***********************************************************************
25 * read_xx_header [internal]
27 static int read_xx_header( HFILE lzfd )
32 LZSeek( lzfd, 0, SEEK_SET );
33 if ( sizeof(mzh) != LZRead( lzfd, &mzh, sizeof(mzh) ) )
35 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
38 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
39 if ( 2 != LZRead( lzfd, magic, 2 ) )
42 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
44 if ( magic[0] == 'N' && magic[1] == 'E' )
45 return IMAGE_OS2_SIGNATURE;
46 if ( magic[0] == 'P' && magic[1] == 'E' )
47 return IMAGE_NT_SIGNATURE;
50 WARN("Can't handle %s files.\n", magic );
54 /***********************************************************************
55 * load_ne_resource [internal]
57 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
58 DWORD *resLen, DWORD *resOff )
60 IMAGE_OS2_HEADER nehd;
61 NE_TYPEINFO *typeInfo;
62 NE_NAMEINFO *nameInfo;
67 /* Read in NE header */
68 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
69 if ( sizeof(nehd) != LZRead( lzfd, &nehd, sizeof(nehd) ) ) return 0;
71 resTabSize = nehd.rname_tab_offset - nehd.resource_tab_offset;
74 TRACE("No resources in NE dll\n" );
78 /* Read in resource table */
79 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
80 if ( !resTab ) return FALSE;
82 LZSeek( lzfd, nehd.resource_tab_offset + nehdoffset, SEEK_SET );
83 if ( resTabSize != LZRead( lzfd, resTab, resTabSize ) )
85 HeapFree( GetProcessHeap(), 0, resTab );
90 typeInfo = (NE_TYPEINFO *)(resTab + 2);
91 typeInfo = NE_FindTypeSection( resTab, typeInfo, typeid );
94 TRACE("No typeid entry found for %p\n", typeid );
95 HeapFree( GetProcessHeap(), 0, resTab );
98 nameInfo = NE_FindResourceFromType( resTab, typeInfo, resid );
101 TRACE("No resid entry found for %p\n", typeid );
102 HeapFree( GetProcessHeap(), 0, resTab );
106 /* Return resource data */
107 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
108 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
110 HeapFree( GetProcessHeap(), 0, resTab );
114 /***********************************************************************
115 * load_pe_resource [internal]
117 static BOOL find_pe_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
118 DWORD *resLen, DWORD *resOff )
120 IMAGE_NT_HEADERS pehd;
122 PIMAGE_DATA_DIRECTORY resDataDir;
123 PIMAGE_SECTION_HEADER sections;
125 DWORD resSectionSize;
127 PIMAGE_RESOURCE_DIRECTORY resPtr;
128 PIMAGE_RESOURCE_DATA_ENTRY resData;
132 /* Read in PE header */
133 pehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
134 if ( sizeof(pehd) != LZRead( lzfd, &pehd, sizeof(pehd) ) ) return 0;
136 resDataDir = pehd.OptionalHeader.DataDirectory+IMAGE_FILE_RESOURCE_DIRECTORY;
137 if ( !resDataDir->Size )
139 TRACE("No resources in PE dll\n" );
143 /* Read in section table */
144 nSections = pehd.FileHeader.NumberOfSections;
145 sections = HeapAlloc( GetProcessHeap(), 0,
146 nSections * sizeof(IMAGE_SECTION_HEADER) );
147 if ( !sections ) return FALSE;
149 LZSeek( lzfd, pehdoffset +
150 sizeof(DWORD) + /* Signature */
151 sizeof(IMAGE_FILE_HEADER) +
152 pehd.FileHeader.SizeOfOptionalHeader, SEEK_SET );
154 if ( nSections * sizeof(IMAGE_SECTION_HEADER) !=
155 LZRead( lzfd, sections, nSections * sizeof(IMAGE_SECTION_HEADER) ) )
157 HeapFree( GetProcessHeap(), 0, sections );
161 /* Find resource section */
162 for ( i = 0; i < nSections; i++ )
163 if ( resDataDir->VirtualAddress >= sections[i].VirtualAddress
164 && resDataDir->VirtualAddress < sections[i].VirtualAddress +
165 sections[i].SizeOfRawData )
168 if ( i == nSections )
170 HeapFree( GetProcessHeap(), 0, sections );
171 TRACE("Couldn't find resource section\n" );
175 /* Read in resource section */
176 resSectionSize = sections[i].SizeOfRawData;
177 resSection = HeapAlloc( GetProcessHeap(), 0, resSectionSize );
180 HeapFree( GetProcessHeap(), 0, sections );
184 LZSeek( lzfd, sections[i].PointerToRawData, SEEK_SET );
185 if ( resSectionSize != LZRead( lzfd, resSection, resSectionSize ) )
187 HeapFree( GetProcessHeap(), 0, resSection );
188 HeapFree( GetProcessHeap(), 0, sections );
193 resDir = (DWORD)resSection +
194 (resDataDir->VirtualAddress - sections[i].VirtualAddress);
196 resPtr = (PIMAGE_RESOURCE_DIRECTORY)resDir;
197 resPtr = GetResDirEntryA( resPtr, typeid, resDir, FALSE );
200 TRACE("No typeid entry found for %p\n", typeid );
201 HeapFree( GetProcessHeap(), 0, resSection );
202 HeapFree( GetProcessHeap(), 0, sections );
205 resPtr = GetResDirEntryA( resPtr, resid, resDir, FALSE );
208 TRACE("No resid entry found for %p\n", resid );
209 HeapFree( GetProcessHeap(), 0, resSection );
210 HeapFree( GetProcessHeap(), 0, sections );
213 resPtr = GetResDirEntryA( resPtr, 0, resDir, TRUE );
216 TRACE("No default language entry found for %p\n", resid );
217 HeapFree( GetProcessHeap(), 0, resSection );
218 HeapFree( GetProcessHeap(), 0, sections );
222 /* Find resource data section */
223 resData = (PIMAGE_RESOURCE_DATA_ENTRY)resPtr;
224 for ( i = 0; i < nSections; i++ )
225 if ( resData->OffsetToData >= sections[i].VirtualAddress
226 && resData->OffsetToData < sections[i].VirtualAddress +
227 sections[i].SizeOfRawData )
230 if ( i == nSections )
232 TRACE("Couldn't find resource data section\n" );
233 HeapFree( GetProcessHeap(), 0, resSection );
234 HeapFree( GetProcessHeap(), 0, sections );
238 /* Return resource data */
239 if ( resLen ) *resLen = resData->Size;
240 if ( resOff ) *resOff = resData->OffsetToData - sections[i].VirtualAddress
241 + sections[i].PointerToRawData;
243 HeapFree( GetProcessHeap(), 0, resSection );
244 HeapFree( GetProcessHeap(), 0, sections );
248 /***********************************************************************
249 * GetFileResourceSize32 [internal]
251 DWORD WINAPI GetFileResourceSize( LPCSTR lpszFileName,
252 LPCSTR lpszResType, LPCSTR lpszResId,
253 LPDWORD lpdwFileOffset )
260 TRACE("(%s,type=0x%lx,id=0x%lx,off=%p)\n",
261 debugstr_a(lpszFileName), (LONG)lpszResType, (LONG)lpszResId,
264 lzfd = LZOpenFileA( lpszFileName, &ofs, OF_READ );
265 if ( !lzfd ) return 0;
267 switch ( read_xx_header( lzfd ) )
269 case IMAGE_OS2_SIGNATURE:
270 retv = find_ne_resource( lzfd, lpszResType, lpszResId,
271 &reslen, lpdwFileOffset );
274 case IMAGE_NT_SIGNATURE:
275 retv = find_pe_resource( lzfd, lpszResType, lpszResId,
276 &reslen, lpdwFileOffset );
281 return retv? reslen : 0;
284 /***********************************************************************
285 * GetFileResource32 [internal]
287 DWORD WINAPI GetFileResource( LPCSTR lpszFileName,
288 LPCSTR lpszResType, LPCSTR lpszResId,
290 DWORD dwResLen, LPVOID lpvData )
295 DWORD reslen = dwResLen;
297 TRACE("(%s,type=0x%lx,id=0x%lx,off=%ld,len=%ld,data=%p)\n",
298 debugstr_a(lpszFileName), (LONG)lpszResType, (LONG)lpszResId,
299 dwFileOffset, dwResLen, lpvData );
301 lzfd = LZOpenFileA( lpszFileName, &ofs, OF_READ );
302 if ( lzfd == 0 ) return 0;
306 switch ( read_xx_header( lzfd ) )
308 case IMAGE_OS2_SIGNATURE:
309 retv = find_ne_resource( lzfd, lpszResType, lpszResId,
310 &reslen, &dwFileOffset );
313 case IMAGE_NT_SIGNATURE:
314 retv = find_pe_resource( lzfd, lpszResType, lpszResId,
315 &reslen, &dwFileOffset );
326 LZSeek( lzfd, dwFileOffset, SEEK_SET );
327 reslen = LZRead( lzfd, lpvData, min( reslen, dwResLen ) );