Replace the get_file_info request by an fstat() on the client side.
[wine] / dlls / kernel / resource.c
1 /*
2  * Resources
3  *
4  * Copyright 1993 Robert J. Amstadt
5  * Copyright 1995, 2003 Alexandre Julliard
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdarg.h>
26
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include "ntstatus.h"
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winreg.h"
33 #include "winternl.h"
34 #include "wownt32.h"
35 #include "wine/winbase16.h"
36 #include "wine/debug.h"
37 #include "excpt.h"
38 #include "wine/exception.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(resource);
41
42 /* handle conversions */
43 #define HRSRC_32(h16)   ((HRSRC)(ULONG_PTR)(h16))
44 #define HRSRC_16(h32)   (LOWORD(h32))
45 #define HGLOBAL_32(h16) ((HGLOBAL)(ULONG_PTR)(h16))
46 #define HGLOBAL_16(h32) (LOWORD(h32))
47 #define HMODULE_16(h32) (LOWORD(h32))
48
49 static WINE_EXCEPTION_FILTER(page_fault)
50 {
51     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ||
52         GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION)
53         return EXCEPTION_EXECUTE_HANDLER;
54     return EXCEPTION_CONTINUE_SEARCH;
55 }
56
57 /* retrieve the resource name to pass to the ntdll functions */
58 static NTSTATUS get_res_nameA( LPCSTR name, UNICODE_STRING *str )
59 {
60     if (!HIWORD(name))
61     {
62         str->Buffer = (LPWSTR)name;
63         return STATUS_SUCCESS;
64     }
65     if (name[0] == '#')
66     {
67         ULONG value;
68         if (RtlCharToInteger( name + 1, 10, &value ) != STATUS_SUCCESS || HIWORD(value))
69             return STATUS_INVALID_PARAMETER;
70         str->Buffer = (LPWSTR)value;
71         return STATUS_SUCCESS;
72     }
73     RtlCreateUnicodeStringFromAsciiz( str, name );
74     RtlUpcaseUnicodeString( str, str, FALSE );
75     return STATUS_SUCCESS;
76 }
77
78 /* retrieve the resource name to pass to the ntdll functions */
79 static NTSTATUS get_res_nameW( LPCWSTR name, UNICODE_STRING *str )
80 {
81     if (!HIWORD(name))
82     {
83         str->Buffer = (LPWSTR)name;
84         return STATUS_SUCCESS;
85     }
86     if (name[0] == '#')
87     {
88         ULONG value;
89         RtlInitUnicodeString( str, name + 1 );
90         if (RtlUnicodeStringToInteger( str, 10, &value ) != STATUS_SUCCESS || HIWORD(value))
91             return STATUS_INVALID_PARAMETER;
92         str->Buffer = (LPWSTR)value;
93         return STATUS_SUCCESS;
94     }
95     RtlCreateUnicodeString( str, name );
96     RtlUpcaseUnicodeString( str, str, FALSE );
97     return STATUS_SUCCESS;
98 }
99
100 /* retrieve the resource names for the 16-bit FindResource function */
101 static BOOL get_res_name_type_WtoA( LPCWSTR name, LPCWSTR type, LPSTR *nameA, LPSTR *typeA )
102 {
103     *nameA = *typeA = NULL;
104
105     __TRY
106     {
107         if (HIWORD(name))
108         {
109             DWORD len = WideCharToMultiByte( CP_ACP, 0, name, -1, NULL, 0, NULL, NULL );
110             *nameA = HeapAlloc( GetProcessHeap(), 0, len );
111             if (*nameA) WideCharToMultiByte( CP_ACP, 0, name, -1, *nameA, len, NULL, NULL );
112         }
113         else *nameA = (LPSTR)name;
114
115         if (HIWORD(type))
116         {
117             DWORD len = WideCharToMultiByte( CP_ACP, 0, type, -1, NULL, 0, NULL, NULL );
118             *typeA = HeapAlloc( GetProcessHeap(), 0, len );
119             if (*typeA) WideCharToMultiByte( CP_ACP, 0, type, -1, *typeA, len, NULL, NULL );
120         }
121         else *typeA = (LPSTR)type;
122     }
123     __EXCEPT(page_fault)
124     {
125         if (HIWORD(*nameA)) HeapFree( GetProcessHeap(), 0, *nameA );
126         if (HIWORD(*typeA)) HeapFree( GetProcessHeap(), 0, *typeA );
127         SetLastError( ERROR_INVALID_PARAMETER );
128         return FALSE;
129     }
130     __ENDTRY
131     return TRUE;
132 }
133
134 /* implementation of FindResourceExA */
135 static HRSRC find_resourceA( HMODULE hModule, LPCSTR type, LPCSTR name, WORD lang )
136 {
137     NTSTATUS status;
138     UNICODE_STRING nameW, typeW;
139     LDR_RESOURCE_INFO info;
140     const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL;
141
142     __TRY
143     {
144         if ((status = get_res_nameA( name, &nameW )) != STATUS_SUCCESS) goto done;
145         if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS) goto done;
146         info.Type = (ULONG)typeW.Buffer;
147         info.Name = (ULONG)nameW.Buffer;
148         info.Language = lang;
149         status = LdrFindResource_U( hModule, &info, 3, &entry );
150     done:
151         if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
152     }
153     __EXCEPT(page_fault)
154     {
155         SetLastError( ERROR_INVALID_PARAMETER );
156     }
157     __ENDTRY
158
159     if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
160     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
161     return (HRSRC)entry;
162 }
163
164
165 /* implementation of FindResourceExW */
166 static HRSRC find_resourceW( HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD lang )
167 {
168     NTSTATUS status;
169     UNICODE_STRING nameW, typeW;
170     LDR_RESOURCE_INFO info;
171     const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL;
172
173     nameW.Buffer = typeW.Buffer = NULL;
174
175     __TRY
176     {
177         if ((status = get_res_nameW( name, &nameW )) != STATUS_SUCCESS) goto done;
178         if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS) goto done;
179         info.Type = (ULONG)typeW.Buffer;
180         info.Name = (ULONG)nameW.Buffer;
181         info.Language = lang;
182         status = LdrFindResource_U( hModule, &info, 3, &entry );
183     done:
184         if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
185     }
186     __EXCEPT(page_fault)
187     {
188         SetLastError( ERROR_INVALID_PARAMETER );
189     }
190     __ENDTRY
191
192     if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
193     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
194     return (HRSRC)entry;
195 }
196
197 /**********************************************************************
198  *          FindResourceExA  (KERNEL32.@)
199  */
200 HRSRC WINAPI FindResourceExA( HMODULE hModule, LPCSTR type, LPCSTR name, WORD lang )
201 {
202     TRACE( "%p %s %s %04x\n", hModule, debugstr_a(type), debugstr_a(name), lang );
203
204     if (!hModule) hModule = GetModuleHandleW(0);
205     else if (!HIWORD(hModule))
206     {
207         return HRSRC_32( FindResource16( HMODULE_16(hModule), name, type ) );
208     }
209     return find_resourceA( hModule, type, name, lang );
210 }
211
212
213 /**********************************************************************
214  *          FindResourceA    (KERNEL32.@)
215  */
216 HRSRC WINAPI FindResourceA( HMODULE hModule, LPCSTR name, LPCSTR type )
217 {
218     return FindResourceExA( hModule, type, name, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
219 }
220
221
222 /**********************************************************************
223  *          FindResourceExW  (KERNEL32.@)
224  */
225 HRSRC WINAPI FindResourceExW( HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD lang )
226 {
227     TRACE( "%p %s %s %04x\n", hModule, debugstr_w(type), debugstr_w(name), lang );
228
229     if (!hModule) hModule = GetModuleHandleW(0);
230     else if (!HIWORD(hModule))
231     {
232         LPSTR nameA, typeA;
233         HRSRC16 ret;
234
235         if (!get_res_name_type_WtoA( name, type, &nameA, &typeA )) return NULL;
236
237         ret = FindResource16( HMODULE_16(hModule), nameA, typeA );
238         if (HIWORD(nameA)) HeapFree( GetProcessHeap(), 0, nameA );
239         if (HIWORD(typeA)) HeapFree( GetProcessHeap(), 0, typeA );
240         return HRSRC_32(ret);
241     }
242
243     return find_resourceW( hModule, type, name, lang );
244 }
245
246
247 /**********************************************************************
248  *          FindResourceW    (KERNEL32.@)
249  */
250 HRSRC WINAPI FindResourceW( HINSTANCE hModule, LPCWSTR name, LPCWSTR type )
251 {
252     return FindResourceExW( hModule, type, name, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
253 }
254
255
256 /**********************************************************************
257  *      EnumResourceTypesA      (KERNEL32.@)
258  */
259 BOOL WINAPI EnumResourceTypesA( HMODULE hmod, ENUMRESTYPEPROCA lpfun, LONG_PTR lparam )
260 {
261     int i;
262     BOOL ret = FALSE;
263     LPSTR type = NULL;
264     DWORD len = 0, newlen;
265     NTSTATUS status;
266     const IMAGE_RESOURCE_DIRECTORY *resdir;
267     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
268     const IMAGE_RESOURCE_DIR_STRING_U *str;
269
270     TRACE( "%p %p %lx\n", hmod, lpfun, lparam );
271
272     if (!hmod) hmod = GetModuleHandleA( NULL );
273
274     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &resdir )) != STATUS_SUCCESS)
275     {
276         SetLastError( RtlNtStatusToDosError(status) );
277         return FALSE;
278     }
279     et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
280     for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
281     {
282         if (et[i].u1.s1.NameIsString)
283         {
284             str = (PIMAGE_RESOURCE_DIR_STRING_U) ((LPBYTE) resdir + et[i].u1.s1.NameOffset);
285             newlen = WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, NULL, 0, NULL, NULL);
286             if (newlen + 1 > len)
287             {
288                 len = newlen + 1;
289                 if (type) HeapFree( GetProcessHeap(), 0, type );
290                 if (!(type = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE;
291             }
292             WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, type, len, NULL, NULL);
293             type[newlen] = 0;
294             ret = lpfun(hmod,type,lparam);
295         }
296         else
297         {
298             ret = lpfun( hmod, (LPSTR)(int)et[i].u1.s2.Id, lparam );
299         }
300         if (!ret) break;
301     }
302     if (type) HeapFree( GetProcessHeap(), 0, type );
303     return ret;
304 }
305
306
307 /**********************************************************************
308  *      EnumResourceTypesW      (KERNEL32.@)
309  */
310 BOOL WINAPI EnumResourceTypesW( HMODULE hmod, ENUMRESTYPEPROCW lpfun, LONG_PTR lparam )
311 {
312     int i;
313     BOOL ret = FALSE;
314     DWORD len = 0;
315     LPWSTR type = NULL;
316     NTSTATUS status;
317     const IMAGE_RESOURCE_DIRECTORY *resdir;
318     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
319     const IMAGE_RESOURCE_DIR_STRING_U *str;
320
321     TRACE( "%p %p %lx\n", hmod, lpfun, lparam );
322
323     if (!hmod) hmod = GetModuleHandleW( NULL );
324
325     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &resdir )) != STATUS_SUCCESS)
326     {
327         SetLastError( RtlNtStatusToDosError(status) );
328         return FALSE;
329     }
330     et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
331     for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++)
332     {
333         if (et[i].u1.s1.NameIsString)
334         {
335             str = (PIMAGE_RESOURCE_DIR_STRING_U) ((LPBYTE) resdir + et[i].u1.s1.NameOffset);
336             if (str->Length + 1 > len)
337             {
338                 len = str->Length + 1;
339                 if (type) HeapFree( GetProcessHeap(), 0, type );
340                 if (!(type = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return FALSE;
341             }
342             memcpy(type, str->NameString, str->Length * sizeof (WCHAR));
343             type[str->Length] = 0;
344             ret = lpfun(hmod,type,lparam);
345         }
346         else
347         {
348             ret = lpfun( hmod, (LPWSTR)(int)et[i].u1.s2.Id, lparam );
349         }
350         if (!ret) break;
351     }
352     if (type) HeapFree( GetProcessHeap(), 0, type );
353     return ret;
354 }
355
356
357 /**********************************************************************
358  *      EnumResourceNamesA      (KERNEL32.@)
359  */
360 BOOL WINAPI EnumResourceNamesA( HMODULE hmod, LPCSTR type, ENUMRESNAMEPROCA lpfun, LONG_PTR lparam )
361 {
362     int i;
363     BOOL ret = FALSE;
364     DWORD len = 0, newlen;
365     LPSTR name = NULL;
366     NTSTATUS status;
367     UNICODE_STRING typeW;
368     LDR_RESOURCE_INFO info;
369     const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir;
370     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
371     const IMAGE_RESOURCE_DIR_STRING_U *str;
372
373     TRACE( "%p %s %p %lx\n", hmod, debugstr_a(type), lpfun, lparam );
374
375     if (!hmod) hmod = GetModuleHandleA( NULL );
376     typeW.Buffer = NULL;
377     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
378         goto done;
379     if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS)
380         goto done;
381     info.Type = (ULONG)typeW.Buffer;
382     if ((status = LdrFindResourceDirectory_U( hmod, &info, 1, &resdir )) != STATUS_SUCCESS)
383         goto done;
384
385     et = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1);
386     for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
387     {
388         if (et[i].u1.s1.NameIsString)
389         {
390             str = (IMAGE_RESOURCE_DIR_STRING_U *) ((LPBYTE) basedir + et[i].u1.s1.NameOffset);
391             newlen = WideCharToMultiByte(CP_ACP, 0, str->NameString, str->Length, NULL, 0, NULL, NULL);
392             if (newlen + 1 > len)
393             {
394                 len = newlen + 1;
395                 if (name) HeapFree( GetProcessHeap(), 0, name );
396                 if (!(name = HeapAlloc(GetProcessHeap(), 0, len + 1 )))
397                 {
398                     ret = FALSE;
399                     break;
400                 }
401             }
402             WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, name, len, NULL, NULL );
403             name[newlen] = 0;
404             ret = lpfun(hmod,type,name,lparam);
405         }
406         else
407         {
408             ret = lpfun( hmod, type, (LPSTR)(int)et[i].u1.s2.Id, lparam );
409         }
410         if (!ret) break;
411     }
412 done:
413     if (name) HeapFree( GetProcessHeap(), 0, name );
414     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
415     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
416     return ret;
417 }
418
419
420 /**********************************************************************
421  *      EnumResourceNamesW      (KERNEL32.@)
422  */
423 BOOL WINAPI EnumResourceNamesW( HMODULE hmod, LPCWSTR type, ENUMRESNAMEPROCW lpfun, LONG_PTR lparam )
424 {
425     int i;
426     BOOL ret = FALSE;
427     LPWSTR name = NULL;
428     DWORD len = 0;
429     NTSTATUS status;
430     UNICODE_STRING typeW;
431     LDR_RESOURCE_INFO info;
432     const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir;
433     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
434     const IMAGE_RESOURCE_DIR_STRING_U *str;
435
436     TRACE( "%p %s %p %lx\n", hmod, debugstr_w(type), lpfun, lparam );
437
438     if (!hmod) hmod = GetModuleHandleW( NULL );
439     typeW.Buffer = NULL;
440     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
441         goto done;
442     if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS)
443         goto done;
444     info.Type = (ULONG)typeW.Buffer;
445     if ((status = LdrFindResourceDirectory_U( hmod, &info, 1, &resdir )) != STATUS_SUCCESS)
446         goto done;
447
448     et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
449     for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
450     {
451         if (et[i].u1.s1.NameIsString)
452         {
453             str = (IMAGE_RESOURCE_DIR_STRING_U *) ((LPBYTE) basedir + et[i].u1.s1.NameOffset);
454             if (str->Length + 1 > len)
455             {
456                 len = str->Length + 1;
457                 if (name) HeapFree( GetProcessHeap(), 0, name );
458                 if (!(name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
459                 {
460                     ret = FALSE;
461                     break;
462                 }
463             }
464             memcpy(name, str->NameString, str->Length * sizeof (WCHAR));
465             name[str->Length] = 0;
466             ret = lpfun(hmod,type,name,lparam);
467         }
468         else
469         {
470             ret = lpfun( hmod, type, (LPWSTR)(int)et[i].u1.s2.Id, lparam );
471         }
472         if (!ret) break;
473     }
474 done:
475     if (name) HeapFree( GetProcessHeap(), 0, name );
476     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
477     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
478     return ret;
479 }
480
481
482 /**********************************************************************
483  *      EnumResourceLanguagesA  (KERNEL32.@)
484  */
485 BOOL WINAPI EnumResourceLanguagesA( HMODULE hmod, LPCSTR type, LPCSTR name,
486                                     ENUMRESLANGPROCA lpfun, LONG_PTR lparam )
487 {
488     int i;
489     BOOL ret = FALSE;
490     NTSTATUS status;
491     UNICODE_STRING typeW, nameW;
492     LDR_RESOURCE_INFO info;
493     const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir;
494     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
495
496     TRACE( "%p %s %s %p %lx\n", hmod, debugstr_a(type), debugstr_a(name), lpfun, lparam );
497
498     if (!hmod) hmod = GetModuleHandleA( NULL );
499     typeW.Buffer = nameW.Buffer = NULL;
500     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
501         goto done;
502     if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS)
503         goto done;
504     if ((status = get_res_nameA( name, &nameW )) != STATUS_SUCCESS)
505         goto done;
506     info.Type = (ULONG)typeW.Buffer;
507     info.Name = (ULONG)nameW.Buffer;
508     if ((status = LdrFindResourceDirectory_U( hmod, &info, 2, &resdir )) != STATUS_SUCCESS)
509         goto done;
510
511     et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
512     for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++)
513     {
514         ret = lpfun( hmod, type, name, et[i].u1.s2.Id, lparam );
515         if (!ret) break;
516     }
517 done:
518     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
519     if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
520     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
521     return ret;
522 }
523
524
525 /**********************************************************************
526  *      EnumResourceLanguagesW  (KERNEL32.@)
527  */
528 BOOL WINAPI EnumResourceLanguagesW( HMODULE hmod, LPCWSTR type, LPCWSTR name,
529                                     ENUMRESLANGPROCW lpfun, LONG_PTR lparam )
530 {
531     int i;
532     BOOL ret = FALSE;
533     NTSTATUS status;
534     UNICODE_STRING typeW, nameW;
535     LDR_RESOURCE_INFO info;
536     const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir;
537     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
538
539     TRACE( "%p %s %s %p %lx\n", hmod, debugstr_w(type), debugstr_w(name), lpfun, lparam );
540
541     if (!hmod) hmod = GetModuleHandleW( NULL );
542     typeW.Buffer = nameW.Buffer = NULL;
543     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
544         goto done;
545     if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS)
546         goto done;
547     if ((status = get_res_nameW( name, &nameW )) != STATUS_SUCCESS)
548         goto done;
549     info.Type = (ULONG)typeW.Buffer;
550     info.Name = (ULONG)nameW.Buffer;
551     if ((status = LdrFindResourceDirectory_U( hmod, &info, 2, &resdir )) != STATUS_SUCCESS)
552         goto done;
553
554     et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
555     for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++)
556     {
557         ret = lpfun( hmod, type, name, et[i].u1.s2.Id, lparam );
558         if (!ret) break;
559     }
560 done:
561     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
562     if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
563     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
564     return ret;
565 }
566
567
568 /**********************************************************************
569  *          LoadResource     (KERNEL32.@)
570  */
571 HGLOBAL WINAPI LoadResource( HINSTANCE hModule, HRSRC hRsrc )
572 {
573     NTSTATUS status;
574     void *ret = NULL;
575
576     TRACE( "%p %p\n", hModule, hRsrc );
577
578     if (hModule && !HIWORD(hModule))
579         /* FIXME: should convert return to 32-bit resource */
580         return HGLOBAL_32( LoadResource16( HMODULE_16(hModule), HRSRC_16(hRsrc) ) );
581
582     if (!hRsrc) return 0;
583     if (!hModule) hModule = GetModuleHandleA( NULL );
584     status = LdrAccessResource( hModule, (IMAGE_RESOURCE_DATA_ENTRY *)hRsrc, &ret, NULL );
585     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
586     return ret;
587 }
588
589
590 /**********************************************************************
591  *          LockResource     (KERNEL32.@)
592  */
593 LPVOID WINAPI LockResource( HGLOBAL handle )
594 {
595     TRACE("(%p)\n", handle );
596
597     if (HIWORD( handle ))  /* 32-bit memory handle */
598         return (LPVOID)handle;
599
600     /* 16-bit memory handle */
601     return LockResource16( HGLOBAL_16(handle) );
602 }
603
604
605 /**********************************************************************
606  *          FreeResource     (KERNEL32.@)
607  */
608 BOOL WINAPI FreeResource( HGLOBAL handle )
609 {
610     if (HIWORD(handle)) return 0; /* 32-bit memory handle: nothing to do */
611     return FreeResource16( HGLOBAL_16(handle) );
612 }
613
614
615 /**********************************************************************
616  *          SizeofResource   (KERNEL32.@)
617  */
618 DWORD WINAPI SizeofResource( HINSTANCE hModule, HRSRC hRsrc )
619 {
620     if (hModule && !HIWORD(hModule))
621         return SizeofResource16( HMODULE_16(hModule), HRSRC_16(hRsrc) );
622
623     if (!hRsrc) return 0;
624     return ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->Size;
625 }
626
627
628 /***********************************************************************
629  *          BeginUpdateResourceA                 (KERNEL32.@)
630  */
631 HANDLE WINAPI BeginUpdateResourceA( LPCSTR pFileName, BOOL bDeleteExistingResources )
632 {
633   FIXME("(%s,%d): stub\n",debugstr_a(pFileName),bDeleteExistingResources);
634   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
635   return 0;
636 }
637
638
639 /***********************************************************************
640  *          BeginUpdateResourceW                 (KERNEL32.@)
641  */
642 HANDLE WINAPI BeginUpdateResourceW( LPCWSTR pFileName, BOOL bDeleteExistingResources )
643 {
644   FIXME("(%s,%d): stub\n",debugstr_w(pFileName),bDeleteExistingResources);
645   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
646   return 0;
647 }
648
649
650 /***********************************************************************
651  *          EndUpdateResourceA                 (KERNEL32.@)
652  */
653 BOOL WINAPI EndUpdateResourceA( HANDLE hUpdate, BOOL fDiscard )
654 {
655   FIXME("(%p,%d): stub\n",hUpdate, fDiscard);
656   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
657   return FALSE;
658 }
659
660
661 /***********************************************************************
662  *          EndUpdateResourceW                 (KERNEL32.@)
663  */
664 BOOL WINAPI EndUpdateResourceW( HANDLE hUpdate, BOOL fDiscard )
665 {
666   FIXME("(%p,%d): stub\n",hUpdate, fDiscard);
667   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
668   return FALSE;
669 }
670
671
672 /***********************************************************************
673  *           UpdateResourceA                 (KERNEL32.@)
674  */
675 BOOL WINAPI UpdateResourceA(
676   HANDLE  hUpdate,
677   LPCSTR  lpType,
678   LPCSTR  lpName,
679   WORD    wLanguage,
680   LPVOID  lpData,
681   DWORD   cbData)
682 {
683   FIXME(": stub\n");
684   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
685   return FALSE;
686 }
687
688
689 /***********************************************************************
690  *           UpdateResourceW                 (KERNEL32.@)
691  */
692 BOOL WINAPI UpdateResourceW(
693   HANDLE  hUpdate,
694   LPCWSTR lpType,
695   LPCWSTR lpName,
696   WORD    wLanguage,
697   LPVOID  lpData,
698   DWORD   cbData)
699 {
700   FIXME(": stub\n");
701   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
702   return FALSE;
703 }