Fixed a couple of races with exiting threads in suspend_for_ptrace().
[wine/gsoc_dplay.git] / loader / pe_resource.c
blobe530d9a3f667470d10a1a7234f018056b812a384
1 /*
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
27 #include "config.h"
29 #include <stdlib.h>
30 #include <sys/types.h>
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
34 #include "wine/unicode.h"
35 #include "windef.h"
36 #include "winnls.h"
37 #include "winternl.h"
38 #include "winerror.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(resource);
44 /**********************************************************************
45 * get_resdir
47 * Get the resource directory of a PE module
49 static const IMAGE_RESOURCE_DIRECTORY* get_resdir( HMODULE hmod )
51 DWORD size;
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);
58 return NULL;
60 return RtlImageDirectoryEntryToData( hmod, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size );
64 /**********************************************************************
65 * find_entry_by_id
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;
73 int min, max, pos;
75 entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
76 min = dir->NumberOfNamedEntries;
77 max = min + dir->NumberOfIdEntries - 1;
78 while (min <= max)
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;
84 else min = pos + 1;
86 return NULL;
90 /**********************************************************************
91 * find_entry_by_nameW
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 );
103 if (name[0] == '#')
105 char buf[16];
106 if (!WideCharToMultiByte( CP_ACP, 0, name+1, -1, buf, sizeof(buf), NULL, NULL ))
107 return NULL;
108 return find_entry_by_id( dir, atoi(buf), root );
111 entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
112 namelen = strlenW(name);
113 min = 0;
114 max = dir->NumberOfNamedEntries - 1;
115 while (min <= max)
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;
123 else min = pos + 1;
125 return NULL;
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;
138 LPWSTR nameW;
139 INT len;
141 if (!HIWORD(name)) return find_entry_by_id( dir, LOWORD(name), root );
142 if (name[0] == '#')
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 );
154 return ret;
158 /**********************************************************************
159 * EnumResourceTypesA (KERNEL32.@)
161 BOOL WINAPI EnumResourceTypesA( HMODULE hmod, ENUMRESTYPEPROCA lpfun, LONG lparam)
163 int i;
164 const IMAGE_RESOURCE_DIRECTORY *resdir = get_resdir(hmod);
165 const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
166 BOOL ret;
168 if (!resdir) return FALSE;
170 et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
171 ret = FALSE;
172 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
173 LPSTR type;
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)))
181 return FALSE;
182 WideCharToMultiByte( CP_ACP, 0, pResString->NameString, pResString->Length,
183 type, len, NULL, NULL);
184 type[len] = '\0';
185 ret = lpfun(hmod,type,lparam);
186 HeapFree(GetProcessHeap(), 0, type);
188 else
190 type = (LPSTR)(int)et[i].u1.s2.Id;
191 ret = lpfun(hmod,type,lparam);
193 if (!ret)
194 break;
196 return ret;
200 /**********************************************************************
201 * EnumResourceTypesW (KERNEL32.@)
203 BOOL WINAPI EnumResourceTypesW( HMODULE hmod, ENUMRESTYPEPROCW lpfun, LONG lparam)
205 int i;
206 const IMAGE_RESOURCE_DIRECTORY *resdir = get_resdir(hmod);
207 const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
208 BOOL ret;
210 if (!resdir) return FALSE;
212 et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
213 ret = FALSE;
214 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
215 LPWSTR type;
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))))
221 return FALSE;
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);
227 else
229 type = (LPWSTR)(int)et[i].u1.s2.Id;
230 ret = lpfun(hmod,type,lparam);
232 if (!ret)
233 break;
235 return ret;
239 /**********************************************************************
240 * EnumResourceNamesA (KERNEL32.@)
242 BOOL WINAPI EnumResourceNamesA( HMODULE hmod, LPCSTR type, ENUMRESNAMEPROCA lpfun, LONG lparam )
244 int i;
245 const IMAGE_RESOURCE_DIRECTORY *basedir = get_resdir(hmod);
246 const IMAGE_RESOURCE_DIRECTORY *resdir;
247 const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
248 BOOL ret;
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);
255 ret = FALSE;
256 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
257 LPSTR name;
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 )))
265 return FALSE;
266 WideCharToMultiByte( CP_ACP, 0, pResString->NameString, pResString->Length,
267 name, len, NULL, NULL );
268 name[len] = '\0';
269 ret = lpfun(hmod,type,name,lparam);
270 HeapFree( GetProcessHeap(), 0, name );
272 else
274 name = (LPSTR)(int)et[i].u1.s2.Id;
275 ret = lpfun(hmod,type,name,lparam);
277 if (!ret)
278 break;
280 return ret;
284 /**********************************************************************
285 * EnumResourceNamesW (KERNEL32.@)
287 BOOL WINAPI EnumResourceNamesW( HMODULE hmod, LPCWSTR type, ENUMRESNAMEPROCW lpfun, LONG lparam )
289 int i;
290 const IMAGE_RESOURCE_DIRECTORY *basedir = get_resdir(hmod);
291 const IMAGE_RESOURCE_DIRECTORY *resdir;
292 const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
293 BOOL ret;
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);
300 ret = FALSE;
301 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
302 LPWSTR name;
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))))
308 return FALSE;
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);
314 else
316 name = (LPWSTR)(int)et[i].u1.s2.Id;
317 ret = lpfun(hmod,type,name,lparam);
319 if (!ret)
320 break;
322 return ret;
326 /**********************************************************************
327 * EnumResourceLanguagesA (KERNEL32.@)
329 BOOL WINAPI EnumResourceLanguagesA( HMODULE hmod, LPCSTR type, LPCSTR name,
330 ENUMRESLANGPROCA lpfun, LONG lparam )
332 int i;
333 const IMAGE_RESOURCE_DIRECTORY *basedir = get_resdir(hmod);
334 const IMAGE_RESOURCE_DIRECTORY *resdir;
335 const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
336 BOOL ret;
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);
343 ret = FALSE;
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);
347 if (!ret)
348 break;
350 return ret;
354 /**********************************************************************
355 * EnumResourceLanguagesW (KERNEL32.@)
357 BOOL WINAPI EnumResourceLanguagesW( HMODULE hmod, LPCWSTR type, LPCWSTR name,
358 ENUMRESLANGPROCW lpfun, LONG lparam )
360 int i;
361 const IMAGE_RESOURCE_DIRECTORY *basedir = get_resdir(hmod);
362 const IMAGE_RESOURCE_DIRECTORY *resdir;
363 const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
364 BOOL ret;
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);
372 ret = FALSE;
373 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
374 ret = lpfun(hmod,type,name,et[i].u1.s2.Id,lparam);
375 if (!ret)
376 break;
378 return ret;