2 * PE (Portable Execute) File Resources
4 * Copyright 1995 Thomas Sandford
5 * Copyright 1996 Martin von Loewis
7 * Based on the Win16 resource handling code in loader/resource.c
8 * Copyright 1993 Robert J. Amstadt
9 * Copyright 1995 Alexandre Julliard
10 * Copyright 1997 Marcus Meissner
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include <sys/types.h>
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
34 #include "wine/unicode.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(resource
);
44 /**********************************************************************
47 * Get the resource directory of a PE module
49 static const IMAGE_RESOURCE_DIRECTORY
* get_resdir( HMODULE hmod
)
53 if (!hmod
) hmod
= GetModuleHandleA( NULL
);
54 else if (!HIWORD(hmod
))
56 FIXME("Enumeration of 16-bit resources is not supported\n");
57 SetLastError(ERROR_INVALID_HANDLE
);
60 return RtlImageDirectoryEntryToData( hmod
, TRUE
, IMAGE_DIRECTORY_ENTRY_RESOURCE
, &size
);
64 /**********************************************************************
67 * Find an entry by id in a resource directory
69 static const IMAGE_RESOURCE_DIRECTORY
*find_entry_by_id( const IMAGE_RESOURCE_DIRECTORY
*dir
,
70 WORD id
, const void *root
)
72 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*entry
;
75 entry
= (const IMAGE_RESOURCE_DIRECTORY_ENTRY
*)(dir
+ 1);
76 min
= dir
->NumberOfNamedEntries
;
77 max
= min
+ dir
->NumberOfIdEntries
- 1;
80 pos
= (min
+ max
) / 2;
81 if (entry
[pos
].u1
.s2
.Id
== id
)
82 return (IMAGE_RESOURCE_DIRECTORY
*)((char *)root
+ entry
[pos
].u2
.s3
.OffsetToDirectory
);
83 if (entry
[pos
].u1
.s2
.Id
> id
) max
= pos
- 1;
90 /**********************************************************************
93 * Find an entry by name in a resource directory
95 static const IMAGE_RESOURCE_DIRECTORY
*find_entry_by_nameW( const IMAGE_RESOURCE_DIRECTORY
*dir
,
96 LPCWSTR name
, const void *root
)
98 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*entry
;
99 const IMAGE_RESOURCE_DIR_STRING_U
*str
;
100 int min
, max
, res
, pos
, namelen
;
102 if (!HIWORD(name
)) return find_entry_by_id( dir
, LOWORD(name
), root
);
106 if (!WideCharToMultiByte( CP_ACP
, 0, name
+1, -1, buf
, sizeof(buf
), NULL
, NULL
))
108 return find_entry_by_id( dir
, atoi(buf
), root
);
111 entry
= (const IMAGE_RESOURCE_DIRECTORY_ENTRY
*)(dir
+ 1);
112 namelen
= strlenW(name
);
114 max
= dir
->NumberOfNamedEntries
- 1;
117 pos
= (min
+ max
) / 2;
118 str
= (IMAGE_RESOURCE_DIR_STRING_U
*)((char *)root
+ entry
[pos
].u1
.s1
.NameOffset
);
119 res
= strncmpiW( name
, str
->NameString
, str
->Length
);
120 if (!res
&& namelen
== str
->Length
)
121 return (IMAGE_RESOURCE_DIRECTORY
*)((char *)root
+ entry
[pos
].u2
.s3
.OffsetToDirectory
);
122 if (res
< 0) max
= pos
- 1;
129 /**********************************************************************
130 * find_entry_by_nameA
132 * Find an entry by name in a resource directory
134 static const IMAGE_RESOURCE_DIRECTORY
*find_entry_by_nameA( const IMAGE_RESOURCE_DIRECTORY
*dir
,
135 LPCSTR name
, const void *root
)
137 const IMAGE_RESOURCE_DIRECTORY
*ret
= NULL
;
141 if (!HIWORD(name
)) return find_entry_by_id( dir
, LOWORD(name
), root
);
144 return find_entry_by_id( dir
, atoi(name
+1), root
);
147 len
= MultiByteToWideChar( CP_ACP
, 0, name
, -1, NULL
, 0 );
148 if ((nameW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
150 MultiByteToWideChar( CP_ACP
, 0, name
, -1, nameW
, len
);
151 ret
= find_entry_by_nameW( dir
, nameW
, root
);
152 HeapFree( GetProcessHeap(), 0, nameW
);
158 /**********************************************************************
159 * EnumResourceTypesA (KERNEL32.@)
161 BOOL WINAPI
EnumResourceTypesA( HMODULE hmod
, ENUMRESTYPEPROCA lpfun
, LONG lparam
)
164 const IMAGE_RESOURCE_DIRECTORY
*resdir
= get_resdir(hmod
);
165 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*et
;
168 if (!resdir
) return FALSE
;
170 et
=(PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(resdir
+ 1);
172 for (i
=0;i
<resdir
->NumberOfNamedEntries
+resdir
->NumberOfIdEntries
;i
++) {
175 if (et
[i
].u1
.s1
.NameIsString
)
177 PIMAGE_RESOURCE_DIR_STRING_U pResString
= (PIMAGE_RESOURCE_DIR_STRING_U
) ((LPBYTE
) resdir
+ et
[i
].u1
.s1
.NameOffset
);
178 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, pResString
->NameString
, pResString
->Length
,
179 NULL
, 0, NULL
, NULL
);
180 if (!(type
= HeapAlloc(GetProcessHeap(), 0, len
+ 1)))
182 WideCharToMultiByte( CP_ACP
, 0, pResString
->NameString
, pResString
->Length
,
183 type
, len
, NULL
, NULL
);
185 ret
= lpfun(hmod
,type
,lparam
);
186 HeapFree(GetProcessHeap(), 0, type
);
190 type
= (LPSTR
)(int)et
[i
].u1
.s2
.Id
;
191 ret
= lpfun(hmod
,type
,lparam
);
200 /**********************************************************************
201 * EnumResourceTypesW (KERNEL32.@)
203 BOOL WINAPI
EnumResourceTypesW( HMODULE hmod
, ENUMRESTYPEPROCW lpfun
, LONG lparam
)
206 const IMAGE_RESOURCE_DIRECTORY
*resdir
= get_resdir(hmod
);
207 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*et
;
210 if (!resdir
) return FALSE
;
212 et
=(PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(resdir
+ 1);
214 for (i
=0;i
<resdir
->NumberOfNamedEntries
+resdir
->NumberOfIdEntries
;i
++) {
217 if (et
[i
].u1
.s1
.NameIsString
)
219 PIMAGE_RESOURCE_DIR_STRING_U pResString
= (PIMAGE_RESOURCE_DIR_STRING_U
) ((LPBYTE
) resdir
+ et
[i
].u1
.s1
.NameOffset
);
220 if (!(type
= HeapAlloc(GetProcessHeap(), 0, (pResString
->Length
+1) * sizeof (WCHAR
))))
222 memcpy(type
, pResString
->NameString
, pResString
->Length
* sizeof (WCHAR
));
223 type
[pResString
->Length
] = '\0';
224 ret
= lpfun(hmod
,type
,lparam
);
225 HeapFree(GetProcessHeap(), 0, type
);
229 type
= (LPWSTR
)(int)et
[i
].u1
.s2
.Id
;
230 ret
= lpfun(hmod
,type
,lparam
);
239 /**********************************************************************
240 * EnumResourceNamesA (KERNEL32.@)
242 BOOL WINAPI
EnumResourceNamesA( HMODULE hmod
, LPCSTR type
, ENUMRESNAMEPROCA lpfun
, LONG lparam
)
245 const IMAGE_RESOURCE_DIRECTORY
*basedir
= get_resdir(hmod
);
246 const IMAGE_RESOURCE_DIRECTORY
*resdir
;
247 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*et
;
250 if (!basedir
) return FALSE
;
252 if (!(resdir
= find_entry_by_nameA( basedir
, type
, basedir
))) return FALSE
;
254 et
=(PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(resdir
+ 1);
256 for (i
=0;i
<resdir
->NumberOfNamedEntries
+resdir
->NumberOfIdEntries
;i
++) {
259 if (et
[i
].u1
.s1
.NameIsString
)
261 PIMAGE_RESOURCE_DIR_STRING_U pResString
= (PIMAGE_RESOURCE_DIR_STRING_U
) ((LPBYTE
) basedir
+ et
[i
].u1
.s1
.NameOffset
);
262 DWORD len
= WideCharToMultiByte(CP_ACP
, 0, pResString
->NameString
, pResString
->Length
,
263 NULL
, 0, NULL
, NULL
);
264 if (!(name
= HeapAlloc(GetProcessHeap(), 0, len
+ 1 )))
266 WideCharToMultiByte( CP_ACP
, 0, pResString
->NameString
, pResString
->Length
,
267 name
, len
, NULL
, NULL
);
269 ret
= lpfun(hmod
,type
,name
,lparam
);
270 HeapFree( GetProcessHeap(), 0, name
);
274 name
= (LPSTR
)(int)et
[i
].u1
.s2
.Id
;
275 ret
= lpfun(hmod
,type
,name
,lparam
);
284 /**********************************************************************
285 * EnumResourceNamesW (KERNEL32.@)
287 BOOL WINAPI
EnumResourceNamesW( HMODULE hmod
, LPCWSTR type
, ENUMRESNAMEPROCW lpfun
, LONG lparam
)
290 const IMAGE_RESOURCE_DIRECTORY
*basedir
= get_resdir(hmod
);
291 const IMAGE_RESOURCE_DIRECTORY
*resdir
;
292 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*et
;
295 if (!basedir
) return FALSE
;
297 if (!(resdir
= find_entry_by_nameW( basedir
, type
, basedir
))) return FALSE
;
299 et
= (PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(resdir
+ 1);
301 for (i
=0;i
<resdir
->NumberOfNamedEntries
+resdir
->NumberOfIdEntries
;i
++) {
304 if (et
[i
].u1
.s1
.NameIsString
)
306 PIMAGE_RESOURCE_DIR_STRING_U pResString
= (PIMAGE_RESOURCE_DIR_STRING_U
) ((LPBYTE
) basedir
+ et
[i
].u1
.s1
.NameOffset
);
307 if (!(name
= HeapAlloc(GetProcessHeap(), 0, (pResString
->Length
+ 1) * sizeof (WCHAR
))))
309 memcpy(name
, pResString
->NameString
, pResString
->Length
* sizeof (WCHAR
));
310 name
[pResString
->Length
] = '\0';
311 ret
= lpfun(hmod
,type
,name
,lparam
);
312 HeapFree(GetProcessHeap(), 0, name
);
316 name
= (LPWSTR
)(int)et
[i
].u1
.s2
.Id
;
317 ret
= lpfun(hmod
,type
,name
,lparam
);
326 /**********************************************************************
327 * EnumResourceLanguagesA (KERNEL32.@)
329 BOOL WINAPI
EnumResourceLanguagesA( HMODULE hmod
, LPCSTR type
, LPCSTR name
,
330 ENUMRESLANGPROCA lpfun
, LONG lparam
)
333 const IMAGE_RESOURCE_DIRECTORY
*basedir
= get_resdir(hmod
);
334 const IMAGE_RESOURCE_DIRECTORY
*resdir
;
335 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*et
;
338 if (!basedir
) return FALSE
;
339 if (!(resdir
= find_entry_by_nameA( basedir
, type
, basedir
))) return FALSE
;
340 if (!(resdir
= find_entry_by_nameA( resdir
, name
, basedir
))) return FALSE
;
342 et
=(PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(resdir
+ 1);
344 for (i
=0;i
<resdir
->NumberOfNamedEntries
+resdir
->NumberOfIdEntries
;i
++) {
345 /* languages are just ids... I hope */
346 ret
= lpfun(hmod
,type
,name
,et
[i
].u1
.s2
.Id
,lparam
);
354 /**********************************************************************
355 * EnumResourceLanguagesW (KERNEL32.@)
357 BOOL WINAPI
EnumResourceLanguagesW( HMODULE hmod
, LPCWSTR type
, LPCWSTR name
,
358 ENUMRESLANGPROCW lpfun
, LONG lparam
)
361 const IMAGE_RESOURCE_DIRECTORY
*basedir
= get_resdir(hmod
);
362 const IMAGE_RESOURCE_DIRECTORY
*resdir
;
363 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*et
;
366 if (!basedir
) return FALSE
;
368 if (!(resdir
= find_entry_by_nameW( basedir
, type
, basedir
))) return FALSE
;
369 if (!(resdir
= find_entry_by_nameW( resdir
, name
, basedir
))) return FALSE
;
371 et
=(PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(resdir
+ 1);
373 for (i
=0;i
<resdir
->NumberOfNamedEntries
+resdir
->NumberOfIdEntries
;i
++) {
374 ret
= lpfun(hmod
,type
,name
,et
[i
].u1
.s2
.Id
,lparam
);