Made OleCreateFontIndirect have the same signature (exactly) as the
[wine] / dlls / version / resource.c
1 /* 
2  * Implementation of VERSION.DLL - Resource Access routines
3  * 
4  * Copyright 1996,1997 Marcus Meissner
5  * Copyright 1997 David Cuthbert
6  * Copyright 1999 Ulrich Weigand
7  */
8
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include "neexe.h"
13 #include "module.h"
14 #include "winver.h"
15 #include "lzexpand.h"
16 #include "debugtools.h"
17
18 DEFAULT_DEBUG_CHANNEL(ver)
19
20
21 /***********************************************************************
22  *           read_xx_header         [internal]
23  */
24 static int read_xx_header( HFILE lzfd )
25 {
26     IMAGE_DOS_HEADER mzh;
27     char magic[3];
28
29     LZSeek( lzfd, 0, SEEK_SET );
30     if ( sizeof(mzh) != LZRead( lzfd, &mzh, sizeof(mzh) ) )
31         return 0;
32     if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
33         return 0;
34
35     LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
36     if ( 2 != LZRead( lzfd, magic, 2 ) )
37         return 0;
38
39     LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
40
41     if ( magic[0] == 'N' && magic[1] == 'E' )
42         return IMAGE_OS2_SIGNATURE;
43     if ( magic[0] == 'P' && magic[1] == 'E' )
44         return IMAGE_NT_SIGNATURE;
45
46     magic[2] = '\0';
47     WARN("Can't handle %s files.\n", magic );
48     return 0;
49 }
50
51 /***********************************************************************
52  *           load_ne_resource         [internal]
53  */
54 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
55                                 DWORD *resLen, DWORD *resOff )
56 {
57     IMAGE_OS2_HEADER nehd;
58     NE_TYPEINFO *typeInfo;
59     NE_NAMEINFO *nameInfo;
60     DWORD nehdoffset;
61     LPBYTE resTab;
62     DWORD resTabSize;
63
64     /* Read in NE header */ 
65     nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
66     if ( sizeof(nehd) != LZRead( lzfd, &nehd, sizeof(nehd) ) ) return 0;
67
68     resTabSize = nehd.rname_tab_offset - nehd.resource_tab_offset; 
69     if ( !resTabSize )
70     {
71         TRACE("No resources in NE dll\n" );
72         return FALSE;
73     }
74
75     /* Read in resource table */ 
76     resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
77     if ( !resTab ) return FALSE;
78
79     LZSeek( lzfd, nehd.resource_tab_offset + nehdoffset, SEEK_SET );
80     if ( resTabSize != LZRead( lzfd, resTab, resTabSize ) )
81     {
82         HeapFree( GetProcessHeap(), 0, resTab );
83         return FALSE;
84     }
85
86     /* Find resource */
87     typeInfo = (NE_TYPEINFO *)(resTab + 2);
88     typeInfo = NE_FindTypeSection( resTab, typeInfo, typeid );
89     if ( !typeInfo )
90     {
91         TRACE("No typeid entry found for %p\n", typeid );
92         HeapFree( GetProcessHeap(), 0, resTab );
93         return FALSE;
94     }
95     nameInfo = NE_FindResourceFromType( resTab, typeInfo, resid );
96     if ( !nameInfo )
97     {
98         TRACE("No resid entry found for %p\n", typeid );
99         HeapFree( GetProcessHeap(), 0, resTab );
100         return FALSE;
101     }
102
103     /* Return resource data */
104     if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
105     if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
106
107     HeapFree( GetProcessHeap(), 0, resTab );
108     return TRUE;
109 }
110
111 /***********************************************************************
112  *           load_pe_resource         [internal]
113  */
114 static BOOL find_pe_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
115                                 DWORD *resLen, DWORD *resOff )
116 {
117     IMAGE_NT_HEADERS pehd;
118     DWORD pehdoffset;
119     PIMAGE_DATA_DIRECTORY resDataDir;
120     PIMAGE_SECTION_HEADER sections;
121     LPBYTE resSection;
122     DWORD resSectionSize;
123     DWORD resDir;
124     PIMAGE_RESOURCE_DIRECTORY resPtr;
125     PIMAGE_RESOURCE_DATA_ENTRY resData;
126     int i, nSections;
127
128
129     /* Read in PE header */
130     pehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
131     if ( sizeof(pehd) != LZRead( lzfd, &pehd, sizeof(pehd) ) ) return 0;
132
133     resDataDir = pehd.OptionalHeader.DataDirectory+IMAGE_FILE_RESOURCE_DIRECTORY;
134     if ( !resDataDir->Size )
135     {
136         TRACE("No resources in PE dll\n" );
137         return FALSE;
138     }
139
140     /* Read in section table */
141     nSections = pehd.FileHeader.NumberOfSections; 
142     sections = HeapAlloc( GetProcessHeap(), 0, 
143                           nSections * sizeof(IMAGE_SECTION_HEADER) );
144     if ( !sections ) return FALSE;
145
146     LZSeek( lzfd, pehdoffset +
147                     sizeof(DWORD) + /* Signature */
148                     sizeof(IMAGE_FILE_HEADER) +
149                     pehd.FileHeader.SizeOfOptionalHeader, SEEK_SET );
150
151     if ( nSections * sizeof(IMAGE_SECTION_HEADER) !=
152          LZRead( lzfd, sections, nSections * sizeof(IMAGE_SECTION_HEADER) ) )
153     {
154         HeapFree( GetProcessHeap(), 0, sections );
155         return FALSE;
156     }
157
158     /* Find resource section */
159     for ( i = 0; i < nSections; i++ )
160         if (    resDataDir->VirtualAddress >= sections[i].VirtualAddress
161              && resDataDir->VirtualAddress <  sections[i].VirtualAddress +
162                                               sections[i].SizeOfRawData )
163             break;
164
165     if ( i == nSections )
166     {
167         HeapFree( GetProcessHeap(), 0, sections );
168         TRACE("Couldn't find resource section\n" );
169         return FALSE;
170     }
171
172     /* Read in resource section */
173     resSectionSize = sections[i].SizeOfRawData; 
174     resSection = HeapAlloc( GetProcessHeap(), 0, resSectionSize );
175     if ( !resSection ) 
176     {
177         HeapFree( GetProcessHeap(), 0, sections );
178         return FALSE;
179     }
180
181     LZSeek( lzfd, sections[i].PointerToRawData, SEEK_SET );
182     if ( resSectionSize != LZRead( lzfd, resSection, resSectionSize ) )
183     {
184         HeapFree( GetProcessHeap(), 0, resSection );
185         HeapFree( GetProcessHeap(), 0, sections );
186         return FALSE;
187     }
188
189     /* Find resource */
190     resDir = (DWORD)resSection + 
191              (resDataDir->VirtualAddress - sections[i].VirtualAddress);
192
193     resPtr = (PIMAGE_RESOURCE_DIRECTORY)resDir;
194     resPtr = GetResDirEntryA( resPtr, typeid, resDir, FALSE );
195     if ( !resPtr )
196     {
197         TRACE("No typeid entry found for %p\n", typeid );
198         HeapFree( GetProcessHeap(), 0, resSection );
199         HeapFree( GetProcessHeap(), 0, sections );
200         return FALSE;
201     }
202     resPtr = GetResDirEntryA( resPtr, resid, resDir, FALSE );
203     if ( !resPtr )
204     {
205         TRACE("No resid entry found for %p\n", resid );
206         HeapFree( GetProcessHeap(), 0, resSection );
207         HeapFree( GetProcessHeap(), 0, sections );
208         return FALSE;
209     }
210     resPtr = GetResDirEntryA( resPtr, 0, resDir, TRUE );
211     if ( !resPtr )
212     {
213         TRACE("No default language entry found for %p\n", resid );
214         HeapFree( GetProcessHeap(), 0, resSection );
215         HeapFree( GetProcessHeap(), 0, sections );
216         return FALSE;
217     }
218
219     /* Find resource data section */
220     resData = (PIMAGE_RESOURCE_DATA_ENTRY)resPtr;
221     for ( i = 0; i < nSections; i++ )
222         if (    resData->OffsetToData >= sections[i].VirtualAddress
223              && resData->OffsetToData <  sections[i].VirtualAddress +
224                                          sections[i].SizeOfRawData )
225             break;
226
227     if ( i == nSections )
228     {
229         TRACE("Couldn't find resource data section\n" );
230         HeapFree( GetProcessHeap(), 0, resSection );
231         HeapFree( GetProcessHeap(), 0, sections );
232         return FALSE;
233     }
234
235     /* Return resource data */
236     if ( resLen ) *resLen = resData->Size;
237     if ( resOff ) *resOff = resData->OffsetToData - sections[i].VirtualAddress
238                             + sections[i].PointerToRawData;
239
240     HeapFree( GetProcessHeap(), 0, resSection );
241     HeapFree( GetProcessHeap(), 0, sections );
242     return TRUE;
243 }
244
245 /***********************************************************************
246  *           GetFileResourceSize32         [internal]
247  */
248 DWORD WINAPI GetFileResourceSize( LPCSTR lpszFileName,
249                                     LPCSTR lpszResType, LPCSTR lpszResId,
250                                     LPDWORD lpdwFileOffset )
251 {
252     BOOL retv = FALSE;
253     HFILE lzfd;
254     OFSTRUCT ofs;
255     DWORD reslen;
256
257     TRACE("(%s,type=0x%lx,id=0x%lx,off=%p)\n",
258                 debugstr_a(lpszFileName), (LONG)lpszResType, (LONG)lpszResId, 
259                 lpszResId );
260
261     lzfd = LZOpenFileA( lpszFileName, &ofs, OF_READ );
262     if ( !lzfd ) return 0;
263
264     switch ( read_xx_header( lzfd ) )
265     {
266     case IMAGE_OS2_SIGNATURE:
267         retv = find_ne_resource( lzfd, lpszResType, lpszResId, 
268                                  &reslen, lpdwFileOffset );
269         break;
270
271     case IMAGE_NT_SIGNATURE:
272         retv = find_pe_resource( lzfd, lpszResType, lpszResId, 
273                                  &reslen, lpdwFileOffset );
274         break;
275     }
276
277     LZClose( lzfd );
278     return retv? reslen : 0;
279 }
280
281 /***********************************************************************
282  *           GetFileResource32         [internal]
283  */
284 DWORD WINAPI GetFileResource( LPCSTR lpszFileName,
285                                 LPCSTR lpszResType, LPCSTR lpszResId,
286                                 DWORD dwFileOffset,
287                                 DWORD dwResLen, LPVOID lpvData )
288 {
289     BOOL retv = FALSE;
290     HFILE lzfd;
291     OFSTRUCT ofs;
292     DWORD reslen = dwResLen;
293
294     TRACE("(%s,type=0x%lx,id=0x%lx,off=%ld,len=%ld,data=%p)\n",
295                 debugstr_a(lpszFileName), (LONG)lpszResType, (LONG)lpszResId, 
296                 dwFileOffset, dwResLen, lpvData );
297
298     lzfd = LZOpenFileA( lpszFileName, &ofs, OF_READ );
299     if ( lzfd == 0 ) return 0;
300
301     if ( !dwFileOffset )
302     {
303         switch ( read_xx_header( lzfd ) ) 
304         {
305         case IMAGE_OS2_SIGNATURE:
306             retv = find_ne_resource( lzfd, lpszResType, lpszResId, 
307                                      &reslen, &dwFileOffset );
308             break;
309
310         case IMAGE_NT_SIGNATURE:
311             retv = find_pe_resource( lzfd, lpszResType, lpszResId, 
312                                      &reslen, &dwFileOffset );
313             break;
314         }
315
316         if ( !retv ) 
317         {
318             LZClose( lzfd );
319             return 0;
320         }
321     }
322
323     LZSeek( lzfd, dwFileOffset, SEEK_SET );
324     reslen = LZRead( lzfd, lpvData, min( reslen, dwResLen ) );
325     LZClose( lzfd );
326
327     return reslen;
328 }
329