2 * Implementation of VERSION.DLL - Resource Access routines
4 * Copyright 1996,1997 Marcus Meissner
5 * Copyright 1997 David Cuthbert
6 * Copyright 1999 Ulrich Weigand
11 #include <sys/types.h>
18 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(ver
);
23 /***********************************************************************
24 * read_xx_header [internal]
26 static int read_xx_header( HFILE lzfd
)
31 LZSeek( lzfd
, 0, SEEK_SET
);
32 if ( sizeof(mzh
) != LZRead( lzfd
, &mzh
, sizeof(mzh
) ) )
34 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
37 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
38 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
41 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
43 if ( magic
[0] == 'N' && magic
[1] == 'E' )
44 return IMAGE_OS2_SIGNATURE
;
45 if ( magic
[0] == 'P' && magic
[1] == 'E' )
46 return IMAGE_NT_SIGNATURE
;
49 WARN("Can't handle %s files.\n", magic
);
53 /***********************************************************************
54 * load_ne_resource [internal]
56 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
57 DWORD
*resLen
, DWORD
*resOff
)
59 IMAGE_OS2_HEADER nehd
;
60 NE_TYPEINFO
*typeInfo
;
61 NE_NAMEINFO
*nameInfo
;
66 /* Read in NE header */
67 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
68 if ( sizeof(nehd
) != LZRead( lzfd
, &nehd
, sizeof(nehd
) ) ) return 0;
70 resTabSize
= nehd
.rname_tab_offset
- nehd
.resource_tab_offset
;
73 TRACE("No resources in NE dll\n" );
77 /* Read in resource table */
78 resTab
= HeapAlloc( GetProcessHeap(), 0, resTabSize
);
79 if ( !resTab
) return FALSE
;
81 LZSeek( lzfd
, nehd
.resource_tab_offset
+ nehdoffset
, SEEK_SET
);
82 if ( resTabSize
!= LZRead( lzfd
, resTab
, resTabSize
) )
84 HeapFree( GetProcessHeap(), 0, resTab
);
89 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
90 typeInfo
= NE_FindTypeSection( resTab
, typeInfo
, typeid );
93 TRACE("No typeid entry found for %p\n", typeid );
94 HeapFree( GetProcessHeap(), 0, resTab
);
97 nameInfo
= NE_FindResourceFromType( resTab
, typeInfo
, resid
);
100 TRACE("No resid entry found for %p\n", typeid );
101 HeapFree( GetProcessHeap(), 0, resTab
);
105 /* Return resource data */
106 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
107 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
109 HeapFree( GetProcessHeap(), 0, resTab
);
113 /***********************************************************************
114 * load_pe_resource [internal]
116 static BOOL
find_pe_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
117 DWORD
*resLen
, DWORD
*resOff
)
119 IMAGE_NT_HEADERS pehd
;
121 PIMAGE_DATA_DIRECTORY resDataDir
;
122 PIMAGE_SECTION_HEADER sections
;
124 DWORD resSectionSize
;
126 PIMAGE_RESOURCE_DIRECTORY resPtr
;
127 PIMAGE_RESOURCE_DATA_ENTRY resData
;
131 /* Read in PE header */
132 pehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
133 if ( sizeof(pehd
) != LZRead( lzfd
, &pehd
, sizeof(pehd
) ) ) return 0;
135 resDataDir
= pehd
.OptionalHeader
.DataDirectory
+IMAGE_FILE_RESOURCE_DIRECTORY
;
136 if ( !resDataDir
->Size
)
138 TRACE("No resources in PE dll\n" );
142 /* Read in section table */
143 nSections
= pehd
.FileHeader
.NumberOfSections
;
144 sections
= HeapAlloc( GetProcessHeap(), 0,
145 nSections
* sizeof(IMAGE_SECTION_HEADER
) );
146 if ( !sections
) return FALSE
;
148 LZSeek( lzfd
, pehdoffset
+
149 sizeof(DWORD
) + /* Signature */
150 sizeof(IMAGE_FILE_HEADER
) +
151 pehd
.FileHeader
.SizeOfOptionalHeader
, SEEK_SET
);
153 if ( nSections
* sizeof(IMAGE_SECTION_HEADER
) !=
154 LZRead( lzfd
, sections
, nSections
* sizeof(IMAGE_SECTION_HEADER
) ) )
156 HeapFree( GetProcessHeap(), 0, sections
);
160 /* Find resource section */
161 for ( i
= 0; i
< nSections
; i
++ )
162 if ( resDataDir
->VirtualAddress
>= sections
[i
].VirtualAddress
163 && resDataDir
->VirtualAddress
< sections
[i
].VirtualAddress
+
164 sections
[i
].SizeOfRawData
)
167 if ( i
== nSections
)
169 HeapFree( GetProcessHeap(), 0, sections
);
170 TRACE("Couldn't find resource section\n" );
174 /* Read in resource section */
175 resSectionSize
= sections
[i
].SizeOfRawData
;
176 resSection
= HeapAlloc( GetProcessHeap(), 0, resSectionSize
);
179 HeapFree( GetProcessHeap(), 0, sections
);
183 LZSeek( lzfd
, sections
[i
].PointerToRawData
, SEEK_SET
);
184 if ( resSectionSize
!= LZRead( lzfd
, resSection
, resSectionSize
) )
186 HeapFree( GetProcessHeap(), 0, resSection
);
187 HeapFree( GetProcessHeap(), 0, sections
);
192 resDir
= (DWORD
)resSection
+
193 (resDataDir
->VirtualAddress
- sections
[i
].VirtualAddress
);
195 resPtr
= (PIMAGE_RESOURCE_DIRECTORY
)resDir
;
196 resPtr
= GetResDirEntryA( resPtr
, typeid, resDir
, FALSE
);
199 TRACE("No typeid entry found for %p\n", typeid );
200 HeapFree( GetProcessHeap(), 0, resSection
);
201 HeapFree( GetProcessHeap(), 0, sections
);
204 resPtr
= GetResDirEntryA( resPtr
, resid
, resDir
, FALSE
);
207 TRACE("No resid entry found for %p\n", resid
);
208 HeapFree( GetProcessHeap(), 0, resSection
);
209 HeapFree( GetProcessHeap(), 0, sections
);
212 resPtr
= GetResDirEntryA( resPtr
, 0, resDir
, TRUE
);
215 TRACE("No default language entry found for %p\n", resid
);
216 HeapFree( GetProcessHeap(), 0, resSection
);
217 HeapFree( GetProcessHeap(), 0, sections
);
221 /* Find resource data section */
222 resData
= (PIMAGE_RESOURCE_DATA_ENTRY
)resPtr
;
223 for ( i
= 0; i
< nSections
; i
++ )
224 if ( resData
->OffsetToData
>= sections
[i
].VirtualAddress
225 && resData
->OffsetToData
< sections
[i
].VirtualAddress
+
226 sections
[i
].SizeOfRawData
)
229 if ( i
== nSections
)
231 TRACE("Couldn't find resource data section\n" );
232 HeapFree( GetProcessHeap(), 0, resSection
);
233 HeapFree( GetProcessHeap(), 0, sections
);
237 /* Return resource data */
238 if ( resLen
) *resLen
= resData
->Size
;
239 if ( resOff
) *resOff
= resData
->OffsetToData
- sections
[i
].VirtualAddress
240 + sections
[i
].PointerToRawData
;
242 HeapFree( GetProcessHeap(), 0, resSection
);
243 HeapFree( GetProcessHeap(), 0, sections
);
247 /***********************************************************************
248 * GetFileResourceSize32 [internal]
250 DWORD WINAPI
GetFileResourceSize( LPCSTR lpszFileName
,
251 LPCSTR lpszResType
, LPCSTR lpszResId
,
252 LPDWORD lpdwFileOffset
)
259 TRACE("(%s,type=0x%lx,id=0x%lx,off=%p)\n",
260 debugstr_a(lpszFileName
), (LONG
)lpszResType
, (LONG
)lpszResId
,
263 lzfd
= LZOpenFileA( lpszFileName
, &ofs
, OF_READ
);
264 if ( !lzfd
) return 0;
266 switch ( read_xx_header( lzfd
) )
268 case IMAGE_OS2_SIGNATURE
:
269 retv
= find_ne_resource( lzfd
, lpszResType
, lpszResId
,
270 &reslen
, lpdwFileOffset
);
273 case IMAGE_NT_SIGNATURE
:
274 retv
= find_pe_resource( lzfd
, lpszResType
, lpszResId
,
275 &reslen
, lpdwFileOffset
);
280 return retv
? reslen
: 0;
283 /***********************************************************************
284 * GetFileResource32 [internal]
286 DWORD WINAPI
GetFileResource( LPCSTR lpszFileName
,
287 LPCSTR lpszResType
, LPCSTR lpszResId
,
289 DWORD dwResLen
, LPVOID lpvData
)
294 DWORD reslen
= dwResLen
;
296 TRACE("(%s,type=0x%lx,id=0x%lx,off=%ld,len=%ld,data=%p)\n",
297 debugstr_a(lpszFileName
), (LONG
)lpszResType
, (LONG
)lpszResId
,
298 dwFileOffset
, dwResLen
, lpvData
);
300 lzfd
= LZOpenFileA( lpszFileName
, &ofs
, OF_READ
);
301 if ( lzfd
== 0 ) return 0;
305 switch ( read_xx_header( lzfd
) )
307 case IMAGE_OS2_SIGNATURE
:
308 retv
= find_ne_resource( lzfd
, lpszResType
, lpszResId
,
309 &reslen
, &dwFileOffset
);
312 case IMAGE_NT_SIGNATURE
:
313 retv
= find_pe_resource( lzfd
, lpszResType
, lpszResId
,
314 &reslen
, &dwFileOffset
);
325 LZSeek( lzfd
, dwFileOffset
, SEEK_SET
);
326 reslen
= LZRead( lzfd
, lpvData
, min( reslen
, dwResLen
) );