2 * Implementation of VERSION.DLL - Resource Access routines
4 * Copyright 1996,1997 Marcus Meissner
5 * Copyright 1997 David Cuthbert
6 * Copyright 1999 Ulrich Weigand
22 DEFAULT_DEBUG_CHANNEL(ver
)
25 /***********************************************************************
26 * read_xx_header [internal]
28 static int read_xx_header( HFILE lzfd
)
33 LZSeek( lzfd
, 0, SEEK_SET
);
34 if ( sizeof(mzh
) != LZRead( lzfd
, &mzh
, sizeof(mzh
) ) )
36 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
39 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
40 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
43 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
45 if ( magic
[0] == 'N' && magic
[1] == 'E' )
46 return IMAGE_OS2_SIGNATURE
;
47 if ( magic
[0] == 'P' && magic
[1] == 'E' )
48 return IMAGE_NT_SIGNATURE
;
51 WARN( ver
, "Can't handle %s files.\n", magic
);
55 /***********************************************************************
56 * load_ne_resource [internal]
58 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
59 DWORD
*resLen
, DWORD
*resOff
)
61 IMAGE_OS2_HEADER nehd
;
62 NE_TYPEINFO
*typeInfo
;
63 NE_NAMEINFO
*nameInfo
;
68 /* Read in NE header */
69 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
70 if ( sizeof(nehd
) != LZRead( lzfd
, &nehd
, sizeof(nehd
) ) ) return 0;
72 resTabSize
= nehd
.rname_tab_offset
- nehd
.resource_tab_offset
;
75 TRACE( ver
, "No resources in NE dll\n" );
79 /* Read in resource table */
80 resTab
= HeapAlloc( GetProcessHeap(), 0, resTabSize
);
81 if ( !resTab
) return FALSE
;
83 LZSeek( lzfd
, nehd
.resource_tab_offset
+ nehdoffset
, SEEK_SET
);
84 if ( resTabSize
!= LZRead( lzfd
, resTab
, resTabSize
) )
86 HeapFree( GetProcessHeap(), 0, resTab
);
91 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
92 typeInfo
= NE_FindTypeSection( resTab
, typeInfo
, typeid );
95 TRACE( ver
, "No typeid entry found for %p\n", typeid );
96 HeapFree( GetProcessHeap(), 0, resTab
);
99 nameInfo
= NE_FindResourceFromType( resTab
, typeInfo
, resid
);
102 TRACE( ver
, "No resid entry found for %p\n", typeid );
103 HeapFree( GetProcessHeap(), 0, resTab
);
107 /* Return resource data */
108 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
109 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
111 HeapFree( GetProcessHeap(), 0, resTab
);
115 /***********************************************************************
116 * load_pe_resource [internal]
118 static BOOL
find_pe_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
119 DWORD
*resLen
, DWORD
*resOff
)
121 IMAGE_NT_HEADERS pehd
;
123 PIMAGE_DATA_DIRECTORY resDataDir
;
124 PIMAGE_SECTION_HEADER sections
;
126 DWORD resSectionSize
;
128 PIMAGE_RESOURCE_DIRECTORY resPtr
;
129 PIMAGE_RESOURCE_DATA_ENTRY resData
;
133 /* Read in PE header */
134 pehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
135 if ( sizeof(pehd
) != LZRead( lzfd
, &pehd
, sizeof(pehd
) ) ) return 0;
137 resDataDir
= pehd
.OptionalHeader
.DataDirectory
+IMAGE_FILE_RESOURCE_DIRECTORY
;
138 if ( !resDataDir
->Size
)
140 TRACE( ver
, "No resources in PE dll\n" );
144 /* Read in section table */
145 nSections
= pehd
.FileHeader
.NumberOfSections
;
146 sections
= HeapAlloc( GetProcessHeap(), 0,
147 nSections
* sizeof(IMAGE_SECTION_HEADER
) );
148 if ( !sections
) return FALSE
;
150 LZSeek( lzfd
, pehdoffset
+
151 sizeof(DWORD
) + /* Signature */
152 sizeof(IMAGE_FILE_HEADER
) +
153 pehd
.FileHeader
.SizeOfOptionalHeader
, SEEK_SET
);
155 if ( nSections
* sizeof(IMAGE_SECTION_HEADER
) !=
156 LZRead( lzfd
, sections
, nSections
* sizeof(IMAGE_SECTION_HEADER
) ) )
158 HeapFree( GetProcessHeap(), 0, sections
);
162 /* Find resource section */
163 for ( i
= 0; i
< nSections
; i
++ )
164 if ( resDataDir
->VirtualAddress
>= sections
[i
].VirtualAddress
165 && resDataDir
->VirtualAddress
< sections
[i
].VirtualAddress
+
166 sections
[i
].SizeOfRawData
)
169 if ( i
== nSections
)
171 HeapFree( GetProcessHeap(), 0, sections
);
172 TRACE( ver
, "Couldn't find resource section\n" );
176 /* Read in resource section */
177 resSectionSize
= sections
[i
].SizeOfRawData
;
178 resSection
= HeapAlloc( GetProcessHeap(), 0, resSectionSize
);
181 HeapFree( GetProcessHeap(), 0, sections
);
185 LZSeek( lzfd
, sections
[i
].PointerToRawData
, SEEK_SET
);
186 if ( resSectionSize
!= LZRead( lzfd
, resSection
, resSectionSize
) )
188 HeapFree( GetProcessHeap(), 0, resSection
);
189 HeapFree( GetProcessHeap(), 0, sections
);
194 resDir
= (DWORD
)resSection
+
195 (resDataDir
->VirtualAddress
- sections
[i
].VirtualAddress
);
197 resPtr
= (PIMAGE_RESOURCE_DIRECTORY
)resDir
;
198 resPtr
= GetResDirEntryA( resPtr
, typeid, resDir
, FALSE
);
201 TRACE( ver
, "No typeid entry found for %p\n", typeid );
202 HeapFree( GetProcessHeap(), 0, resSection
);
203 HeapFree( GetProcessHeap(), 0, sections
);
206 resPtr
= GetResDirEntryA( resPtr
, resid
, resDir
, FALSE
);
209 TRACE( ver
, "No resid entry found for %p\n", resid
);
210 HeapFree( GetProcessHeap(), 0, resSection
);
211 HeapFree( GetProcessHeap(), 0, sections
);
214 resPtr
= GetResDirEntryA( resPtr
, 0, resDir
, TRUE
);
217 TRACE( ver
, "No default language entry found for %p\n", resid
);
218 HeapFree( GetProcessHeap(), 0, resSection
);
219 HeapFree( GetProcessHeap(), 0, sections
);
223 /* Find resource data section */
224 resData
= (PIMAGE_RESOURCE_DATA_ENTRY
)resPtr
;
225 for ( i
= 0; i
< nSections
; i
++ )
226 if ( resData
->OffsetToData
>= sections
[i
].VirtualAddress
227 && resData
->OffsetToData
< sections
[i
].VirtualAddress
+
228 sections
[i
].SizeOfRawData
)
231 if ( i
== nSections
)
233 TRACE( ver
, "Couldn't find resource data section\n" );
234 HeapFree( GetProcessHeap(), 0, resSection
);
235 HeapFree( GetProcessHeap(), 0, sections
);
239 /* Return resource data */
240 if ( resLen
) *resLen
= resData
->Size
;
241 if ( resOff
) *resOff
= resData
->OffsetToData
- sections
[i
].VirtualAddress
242 + sections
[i
].PointerToRawData
;
244 HeapFree( GetProcessHeap(), 0, resSection
);
245 HeapFree( GetProcessHeap(), 0, sections
);
249 /***********************************************************************
250 * GetFileResourceSize32 [internal]
252 DWORD WINAPI
GetFileResourceSize( LPCSTR lpszFileName
,
253 LPCSTR lpszResType
, LPCSTR lpszResId
,
254 LPDWORD lpdwFileOffset
)
261 TRACE( ver
, "(%s,type=0x%lx,id=0x%lx,off=%p)\n",
262 debugstr_a(lpszFileName
), (LONG
)lpszResType
, (LONG
)lpszResId
,
265 lzfd
= LZOpenFileA( lpszFileName
, &ofs
, OF_READ
);
266 if ( !lzfd
) return 0;
268 switch ( read_xx_header( lzfd
) )
270 case IMAGE_OS2_SIGNATURE
:
271 retv
= find_ne_resource( lzfd
, lpszResType
, lpszResId
,
272 &reslen
, lpdwFileOffset
);
275 case IMAGE_NT_SIGNATURE
:
276 retv
= find_pe_resource( lzfd
, lpszResType
, lpszResId
,
277 &reslen
, lpdwFileOffset
);
282 return retv
? reslen
: 0;
285 /***********************************************************************
286 * GetFileResource32 [internal]
288 DWORD WINAPI
GetFileResource( LPCSTR lpszFileName
,
289 LPCSTR lpszResType
, LPCSTR lpszResId
,
291 DWORD dwResLen
, LPVOID lpvData
)
296 DWORD reslen
= dwResLen
;
298 TRACE( ver
, "(%s,type=0x%lx,id=0x%lx,off=%ld,len=%ld,data=%p)\n",
299 debugstr_a(lpszFileName
), (LONG
)lpszResType
, (LONG
)lpszResId
,
300 dwFileOffset
, dwResLen
, lpvData
);
302 lzfd
= LZOpenFileA( lpszFileName
, &ofs
, OF_READ
);
303 if ( lzfd
== 0 ) return 0;
307 switch ( read_xx_header( lzfd
) )
309 case IMAGE_OS2_SIGNATURE
:
310 retv
= find_ne_resource( lzfd
, lpszResType
, lpszResId
,
311 &reslen
, &dwFileOffset
);
314 case IMAGE_NT_SIGNATURE
:
315 retv
= find_pe_resource( lzfd
, lpszResType
, lpszResId
,
316 &reslen
, &dwFileOffset
);
327 LZSeek( lzfd
, dwFileOffset
, SEEK_SET
);
328 reslen
= LZRead( lzfd
, lpvData
, min( reslen
, dwResLen
) );