Fix obviously wrong condition in an "if" statement.
[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 #include "wine/unicode.h"
40 #include "wine/list.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(resource);
43
44 /* handle conversions */
45 #define HRSRC_32(h16)   ((HRSRC)(ULONG_PTR)(h16))
46 #define HRSRC_16(h32)   (LOWORD(h32))
47 #define HGLOBAL_32(h16) ((HGLOBAL)(ULONG_PTR)(h16))
48 #define HGLOBAL_16(h32) (LOWORD(h32))
49 #define HMODULE_16(h32) (LOWORD(h32))
50
51 static WINE_EXCEPTION_FILTER(page_fault)
52 {
53     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ||
54         GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION)
55         return EXCEPTION_EXECUTE_HANDLER;
56     return EXCEPTION_CONTINUE_SEARCH;
57 }
58
59 /* retrieve the resource name to pass to the ntdll functions */
60 static NTSTATUS get_res_nameA( LPCSTR name, UNICODE_STRING *str )
61 {
62     if (!HIWORD(name))
63     {
64         str->Buffer = (LPWSTR)name;
65         return STATUS_SUCCESS;
66     }
67     if (name[0] == '#')
68     {
69         ULONG value;
70         if (RtlCharToInteger( name + 1, 10, &value ) != STATUS_SUCCESS || HIWORD(value))
71             return STATUS_INVALID_PARAMETER;
72         str->Buffer = (LPWSTR)value;
73         return STATUS_SUCCESS;
74     }
75     RtlCreateUnicodeStringFromAsciiz( str, name );
76     RtlUpcaseUnicodeString( str, str, FALSE );
77     return STATUS_SUCCESS;
78 }
79
80 /* retrieve the resource name to pass to the ntdll functions */
81 static NTSTATUS get_res_nameW( LPCWSTR name, UNICODE_STRING *str )
82 {
83     if (!HIWORD(name))
84     {
85         str->Buffer = (LPWSTR)name;
86         return STATUS_SUCCESS;
87     }
88     if (name[0] == '#')
89     {
90         ULONG value;
91         RtlInitUnicodeString( str, name + 1 );
92         if (RtlUnicodeStringToInteger( str, 10, &value ) != STATUS_SUCCESS || HIWORD(value))
93             return STATUS_INVALID_PARAMETER;
94         str->Buffer = (LPWSTR)value;
95         return STATUS_SUCCESS;
96     }
97     RtlCreateUnicodeString( str, name );
98     RtlUpcaseUnicodeString( str, str, FALSE );
99     return STATUS_SUCCESS;
100 }
101
102 /* retrieve the resource names for the 16-bit FindResource function */
103 static BOOL get_res_name_type_WtoA( LPCWSTR name, LPCWSTR type, LPSTR *nameA, LPSTR *typeA )
104 {
105     *nameA = *typeA = NULL;
106
107     __TRY
108     {
109         if (HIWORD(name))
110         {
111             DWORD len = WideCharToMultiByte( CP_ACP, 0, name, -1, NULL, 0, NULL, NULL );
112             *nameA = HeapAlloc( GetProcessHeap(), 0, len );
113             if (*nameA) WideCharToMultiByte( CP_ACP, 0, name, -1, *nameA, len, NULL, NULL );
114         }
115         else *nameA = (LPSTR)name;
116
117         if (HIWORD(type))
118         {
119             DWORD len = WideCharToMultiByte( CP_ACP, 0, type, -1, NULL, 0, NULL, NULL );
120             *typeA = HeapAlloc( GetProcessHeap(), 0, len );
121             if (*typeA) WideCharToMultiByte( CP_ACP, 0, type, -1, *typeA, len, NULL, NULL );
122         }
123         else *typeA = (LPSTR)type;
124     }
125     __EXCEPT(page_fault)
126     {
127         if (HIWORD(*nameA)) HeapFree( GetProcessHeap(), 0, *nameA );
128         if (HIWORD(*typeA)) HeapFree( GetProcessHeap(), 0, *typeA );
129         SetLastError( ERROR_INVALID_PARAMETER );
130         return FALSE;
131     }
132     __ENDTRY
133     return TRUE;
134 }
135
136 /* implementation of FindResourceExA */
137 static HRSRC find_resourceA( HMODULE hModule, LPCSTR type, LPCSTR name, WORD lang )
138 {
139     NTSTATUS status;
140     UNICODE_STRING nameW, typeW;
141     LDR_RESOURCE_INFO info;
142     const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL;
143
144     __TRY
145     {
146         if ((status = get_res_nameA( name, &nameW )) != STATUS_SUCCESS) goto done;
147         if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS) goto done;
148         info.Type = (ULONG)typeW.Buffer;
149         info.Name = (ULONG)nameW.Buffer;
150         info.Language = lang;
151         status = LdrFindResource_U( hModule, &info, 3, &entry );
152     done:
153         if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
154     }
155     __EXCEPT(page_fault)
156     {
157         SetLastError( ERROR_INVALID_PARAMETER );
158     }
159     __ENDTRY
160
161     if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
162     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
163     return (HRSRC)entry;
164 }
165
166
167 /* implementation of FindResourceExW */
168 static HRSRC find_resourceW( HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD lang )
169 {
170     NTSTATUS status;
171     UNICODE_STRING nameW, typeW;
172     LDR_RESOURCE_INFO info;
173     const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL;
174
175     nameW.Buffer = typeW.Buffer = NULL;
176
177     __TRY
178     {
179         if ((status = get_res_nameW( name, &nameW )) != STATUS_SUCCESS) goto done;
180         if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS) goto done;
181         info.Type = (ULONG)typeW.Buffer;
182         info.Name = (ULONG)nameW.Buffer;
183         info.Language = lang;
184         status = LdrFindResource_U( hModule, &info, 3, &entry );
185     done:
186         if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
187     }
188     __EXCEPT(page_fault)
189     {
190         SetLastError( ERROR_INVALID_PARAMETER );
191     }
192     __ENDTRY
193
194     if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
195     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
196     return (HRSRC)entry;
197 }
198
199 /**********************************************************************
200  *          FindResourceExA  (KERNEL32.@)
201  */
202 HRSRC WINAPI FindResourceExA( HMODULE hModule, LPCSTR type, LPCSTR name, WORD lang )
203 {
204     TRACE( "%p %s %s %04x\n", hModule, debugstr_a(type), debugstr_a(name), lang );
205
206     if (!hModule) hModule = GetModuleHandleW(0);
207     else if (!HIWORD(hModule))
208     {
209         return HRSRC_32( FindResource16( HMODULE_16(hModule), name, type ) );
210     }
211     return find_resourceA( hModule, type, name, lang );
212 }
213
214
215 /**********************************************************************
216  *          FindResourceA    (KERNEL32.@)
217  */
218 HRSRC WINAPI FindResourceA( HMODULE hModule, LPCSTR name, LPCSTR type )
219 {
220     return FindResourceExA( hModule, type, name, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
221 }
222
223
224 /**********************************************************************
225  *          FindResourceExW  (KERNEL32.@)
226  */
227 HRSRC WINAPI FindResourceExW( HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD lang )
228 {
229     TRACE( "%p %s %s %04x\n", hModule, debugstr_w(type), debugstr_w(name), lang );
230
231     if (!hModule) hModule = GetModuleHandleW(0);
232     else if (!HIWORD(hModule))
233     {
234         LPSTR nameA, typeA;
235         HRSRC16 ret;
236
237         if (!get_res_name_type_WtoA( name, type, &nameA, &typeA )) return NULL;
238
239         ret = FindResource16( HMODULE_16(hModule), nameA, typeA );
240         if (HIWORD(nameA)) HeapFree( GetProcessHeap(), 0, nameA );
241         if (HIWORD(typeA)) HeapFree( GetProcessHeap(), 0, typeA );
242         return HRSRC_32(ret);
243     }
244
245     return find_resourceW( hModule, type, name, lang );
246 }
247
248
249 /**********************************************************************
250  *          FindResourceW    (KERNEL32.@)
251  */
252 HRSRC WINAPI FindResourceW( HINSTANCE hModule, LPCWSTR name, LPCWSTR type )
253 {
254     return FindResourceExW( hModule, type, name, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
255 }
256
257
258 /**********************************************************************
259  *      EnumResourceTypesA      (KERNEL32.@)
260  */
261 BOOL WINAPI EnumResourceTypesA( HMODULE hmod, ENUMRESTYPEPROCA lpfun, LONG_PTR lparam )
262 {
263     int i;
264     BOOL ret = FALSE;
265     LPSTR type = NULL;
266     DWORD len = 0, newlen;
267     NTSTATUS status;
268     const IMAGE_RESOURCE_DIRECTORY *resdir;
269     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
270     const IMAGE_RESOURCE_DIR_STRING_U *str;
271
272     TRACE( "%p %p %lx\n", hmod, lpfun, lparam );
273
274     if (!hmod) hmod = GetModuleHandleA( NULL );
275
276     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &resdir )) != STATUS_SUCCESS)
277     {
278         SetLastError( RtlNtStatusToDosError(status) );
279         return FALSE;
280     }
281     et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
282     for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
283     {
284         if (et[i].u1.s1.NameIsString)
285         {
286             str = (PIMAGE_RESOURCE_DIR_STRING_U) ((LPBYTE) resdir + et[i].u1.s1.NameOffset);
287             newlen = WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, NULL, 0, NULL, NULL);
288             if (newlen + 1 > len)
289             {
290                 len = newlen + 1;
291                 if (type) HeapFree( GetProcessHeap(), 0, type );
292                 if (!(type = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE;
293             }
294             WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, type, len, NULL, NULL);
295             type[newlen] = 0;
296             ret = lpfun(hmod,type,lparam);
297         }
298         else
299         {
300             ret = lpfun( hmod, (LPSTR)(int)et[i].u1.s2.Id, lparam );
301         }
302         if (!ret) break;
303     }
304     if (type) HeapFree( GetProcessHeap(), 0, type );
305     return ret;
306 }
307
308
309 /**********************************************************************
310  *      EnumResourceTypesW      (KERNEL32.@)
311  */
312 BOOL WINAPI EnumResourceTypesW( HMODULE hmod, ENUMRESTYPEPROCW lpfun, LONG_PTR lparam )
313 {
314     int i, len = 0;
315     BOOL ret = FALSE;
316     LPWSTR type = NULL;
317     NTSTATUS status;
318     const IMAGE_RESOURCE_DIRECTORY *resdir;
319     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
320     const IMAGE_RESOURCE_DIR_STRING_U *str;
321
322     TRACE( "%p %p %lx\n", hmod, lpfun, lparam );
323
324     if (!hmod) hmod = GetModuleHandleW( NULL );
325
326     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &resdir )) != STATUS_SUCCESS)
327     {
328         SetLastError( RtlNtStatusToDosError(status) );
329         return FALSE;
330     }
331     et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
332     for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++)
333     {
334         if (et[i].u1.s1.NameIsString)
335         {
336             str = (PIMAGE_RESOURCE_DIR_STRING_U) ((LPBYTE) resdir + et[i].u1.s1.NameOffset);
337             if (str->Length + 1 > len)
338             {
339                 len = str->Length + 1;
340                 if (type) HeapFree( GetProcessHeap(), 0, type );
341                 if (!(type = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return FALSE;
342             }
343             memcpy(type, str->NameString, str->Length * sizeof (WCHAR));
344             type[str->Length] = 0;
345             ret = lpfun(hmod,type,lparam);
346         }
347         else
348         {
349             ret = lpfun( hmod, (LPWSTR)(int)et[i].u1.s2.Id, lparam );
350         }
351         if (!ret) break;
352     }
353     if (type) HeapFree( GetProcessHeap(), 0, type );
354     return ret;
355 }
356
357
358 /**********************************************************************
359  *      EnumResourceNamesA      (KERNEL32.@)
360  */
361 BOOL WINAPI EnumResourceNamesA( HMODULE hmod, LPCSTR type, ENUMRESNAMEPROCA lpfun, LONG_PTR lparam )
362 {
363     int i;
364     BOOL ret = FALSE;
365     DWORD len = 0, newlen;
366     LPSTR name = NULL;
367     NTSTATUS status;
368     UNICODE_STRING typeW;
369     LDR_RESOURCE_INFO info;
370     const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir;
371     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
372     const IMAGE_RESOURCE_DIR_STRING_U *str;
373
374     TRACE( "%p %s %p %lx\n", hmod, debugstr_a(type), lpfun, lparam );
375
376     if (!hmod) hmod = GetModuleHandleA( NULL );
377     typeW.Buffer = NULL;
378     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
379         goto done;
380     if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS)
381         goto done;
382     info.Type = (ULONG)typeW.Buffer;
383     if ((status = LdrFindResourceDirectory_U( hmod, &info, 1, &resdir )) != STATUS_SUCCESS)
384         goto done;
385
386     et = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1);
387     for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
388     {
389         if (et[i].u1.s1.NameIsString)
390         {
391             str = (IMAGE_RESOURCE_DIR_STRING_U *) ((LPBYTE) basedir + et[i].u1.s1.NameOffset);
392             newlen = WideCharToMultiByte(CP_ACP, 0, str->NameString, str->Length, NULL, 0, NULL, NULL);
393             if (newlen + 1 > len)
394             {
395                 len = newlen + 1;
396                 if (name) HeapFree( GetProcessHeap(), 0, name );
397                 if (!(name = HeapAlloc(GetProcessHeap(), 0, len + 1 )))
398                 {
399                     ret = FALSE;
400                     break;
401                 }
402             }
403             WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, name, len, NULL, NULL );
404             name[newlen] = 0;
405             ret = lpfun(hmod,type,name,lparam);
406         }
407         else
408         {
409             ret = lpfun( hmod, type, (LPSTR)(int)et[i].u1.s2.Id, lparam );
410         }
411         if (!ret) break;
412     }
413 done:
414     if (name) HeapFree( GetProcessHeap(), 0, name );
415     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
416     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
417     return ret;
418 }
419
420
421 /**********************************************************************
422  *      EnumResourceNamesW      (KERNEL32.@)
423  */
424 BOOL WINAPI EnumResourceNamesW( HMODULE hmod, LPCWSTR type, ENUMRESNAMEPROCW lpfun, LONG_PTR lparam )
425 {
426     int i, len = 0;
427     BOOL ret = FALSE;
428     LPWSTR name = NULL;
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 typedef struct
629 {
630     LPWSTR pFileName;
631     struct list resources_list;
632 } QUEUEDUPDATES;
633
634 typedef struct
635 {
636     struct list entry;
637     LPWSTR lpType;
638     LPWSTR lpName;
639     WORD wLanguage;
640     LPVOID lpData;
641     DWORD cbData;
642 } QUEUEDRESOURCE;
643
644 static BOOL CALLBACK enum_resources_languages_delete_all(HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, WORD wLang, LONG_PTR lParam)
645 {
646     return UpdateResourceW((HANDLE)lParam, lpType, lpName, wLang, NULL, 0);
647 }
648
649 static BOOL CALLBACK enum_resources_names_delete_all(HMODULE hModule, LPCWSTR lpType, LPWSTR lpName, LONG_PTR lParam)
650 {
651     return EnumResourceLanguagesW(hModule, lpType, lpName, enum_resources_languages_delete_all, lParam);
652 }
653
654 static BOOL CALLBACK enum_resources_types_delete_all(HMODULE hModule, LPWSTR lpType, LONG_PTR lParam)
655 {
656     return EnumResourceNamesW(hModule, lpType, enum_resources_names_delete_all, lParam);
657 }
658
659 /***********************************************************************
660  *          BeginUpdateResourceW                 (KERNEL32.@)
661  */
662 HANDLE WINAPI BeginUpdateResourceW( LPCWSTR pFileName, BOOL bDeleteExistingResources )
663 {
664     HANDLE hFile = NULL;
665     WIN32_FIND_DATAW fd;
666     HANDLE hModule = NULL;
667     HANDLE hUpdate = NULL;
668     QUEUEDUPDATES *current_updates = NULL;
669     HANDLE ret = NULL;
670
671     TRACE("%s, %d\n",debugstr_w(pFileName),bDeleteExistingResources);
672
673     hFile = FindFirstFileW(pFileName, &fd);
674     if(hFile == INVALID_HANDLE_VALUE)
675     {
676         hFile = NULL;
677         SetLastError(ERROR_FILE_NOT_FOUND);
678         goto done;
679     }
680     if(fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
681     {
682         SetLastError(ERROR_FILE_READ_ONLY);
683         goto done;
684     }
685
686     hModule = LoadLibraryW(pFileName);
687     if(hModule == NULL)
688     {
689         SetLastError(ERROR_INVALID_PARAMETER);
690         goto done;
691     }
692
693     if(!(hUpdate = GlobalAlloc(GHND, sizeof(QUEUEDUPDATES))))
694     {
695         SetLastError(ERROR_OUTOFMEMORY);
696         goto done;
697     }
698     if(!(current_updates = GlobalLock(hUpdate)))
699     {
700         SetLastError(ERROR_INVALID_HANDLE);
701         goto done;
702     }
703     if(!(current_updates->pFileName = HeapAlloc(GetProcessHeap(), 0, (strlenW(pFileName)+1)*sizeof(WCHAR))))
704     {
705         SetLastError(ERROR_OUTOFMEMORY);
706         goto done;
707     }
708     strcpyW(current_updates->pFileName, pFileName);
709     list_init(&current_updates->resources_list);
710
711     if(bDeleteExistingResources)
712         if(!EnumResourceTypesW(hModule, enum_resources_types_delete_all, (LONG_PTR)&current_updates))
713             goto done;
714     ret = hUpdate;
715
716 done:
717     if(!ret && current_updates)
718     {
719         if(current_updates->pFileName) HeapFree(GetProcessHeap(), 0, current_updates->pFileName);
720         GlobalUnlock(hUpdate);
721         GlobalFree(hUpdate);
722         hUpdate = NULL;
723     }
724     if(hUpdate) GlobalUnlock(hUpdate);
725     if(hModule) FreeLibrary(hModule);
726     if(hFile) FindClose(hFile);
727     return ret;
728 }
729
730
731 /***********************************************************************
732  *          BeginUpdateResourceA                 (KERNEL32.@)
733  */
734 HANDLE WINAPI BeginUpdateResourceA( LPCSTR pFileName, BOOL bDeleteExistingResources )
735 {
736     UNICODE_STRING FileNameW;
737     HANDLE ret;
738     RtlCreateUnicodeStringFromAsciiz(&FileNameW, pFileName);
739     ret = BeginUpdateResourceW(FileNameW.Buffer, bDeleteExistingResources);
740     RtlFreeUnicodeString(&FileNameW);
741     return ret;
742 }
743
744
745 /***********************************************************************
746  *          EndUpdateResourceW                 (KERNEL32.@)
747  */
748 BOOL WINAPI EndUpdateResourceW( HANDLE hUpdate, BOOL fDiscard )
749 {
750     QUEUEDUPDATES *current_updates = NULL;
751     BOOL found = TRUE;
752     BOOL ret = FALSE;
753     struct list *ptr = NULL;
754     QUEUEDRESOURCE *current_resource = NULL;
755
756     FIXME("(%p,%d): stub\n",hUpdate,fDiscard);
757
758     if(!(current_updates = GlobalLock(hUpdate)))
759     {
760         SetLastError(ERROR_INVALID_HANDLE);
761         found = FALSE;
762         goto done;
763     }
764
765     if(fDiscard)
766         ret = TRUE;
767     else
768     {
769         /* FIXME: This is the only missing part, an actual implementation */
770         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
771         ret = FALSE;
772     }
773
774 done:
775     if(found)
776     {
777         while ((ptr = list_head(&current_updates->resources_list)) != NULL)
778         {
779             current_resource = LIST_ENTRY(ptr, QUEUEDRESOURCE, entry);
780             list_remove(&current_resource->entry);
781             if(HIWORD(current_resource->lpType)) HeapFree(GetProcessHeap(), 0, current_resource->lpType);
782             if(HIWORD(current_resource->lpName)) HeapFree(GetProcessHeap(), 0, current_resource->lpName);
783             if(current_resource->lpData) HeapFree(GetProcessHeap(), 0, current_resource->lpData);
784             HeapFree(GetProcessHeap(), 0, current_resource);
785         }
786         if(current_updates->pFileName) HeapFree(GetProcessHeap(), 0, current_updates->pFileName);
787         GlobalUnlock(hUpdate);
788         GlobalFree(hUpdate);
789     }
790     return ret;
791 }
792
793
794 /***********************************************************************
795  *          EndUpdateResourceA                 (KERNEL32.@)
796  */
797 BOOL WINAPI EndUpdateResourceA( HANDLE hUpdate, BOOL fDiscard )
798 {
799     return EndUpdateResourceW(hUpdate, fDiscard);
800 }
801
802
803 /***********************************************************************
804  *           UpdateResourceW                 (KERNEL32.@)
805  */
806 BOOL WINAPI UpdateResourceW( HANDLE hUpdate, LPCWSTR lpType, LPCWSTR lpName,
807                              WORD wLanguage, LPVOID lpData, DWORD cbData)
808 {
809     QUEUEDUPDATES *current_updates = NULL;
810     BOOL found = TRUE;
811     QUEUEDRESOURCE *current_resource = NULL;
812     BOOL ret = FALSE;
813
814     TRACE("%p %s %s %08x %p %ld\n",hUpdate,debugstr_w(lpType),debugstr_w(lpName),wLanguage,lpData,cbData);
815
816     if(!(current_updates = GlobalLock(hUpdate)))
817     {
818         SetLastError(ERROR_INVALID_HANDLE);
819         found = FALSE;
820         goto done;
821     }
822
823     if(!(current_resource = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUEDRESOURCE))))
824     {
825         SetLastError(ERROR_OUTOFMEMORY);
826         goto done;
827     }
828     if(!HIWORD(lpType))
829         current_resource->lpType = (LPWSTR)lpType;
830     else if((current_resource->lpType = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpType)+1)*sizeof(WCHAR))))
831         strcpyW(current_resource->lpType, lpType);
832     else
833     {
834         SetLastError(ERROR_OUTOFMEMORY);
835         goto done;
836     }
837     if(!HIWORD(lpName))
838         current_resource->lpName = (LPWSTR)lpName;
839     else if((current_resource->lpName = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpName)+1)*sizeof(WCHAR))))
840         strcpyW(current_resource->lpName, lpName);
841     else
842     {
843         SetLastError(ERROR_OUTOFMEMORY);
844         goto done;
845     }
846     if(!(current_resource->lpData = HeapAlloc(GetProcessHeap(), 0, cbData)))
847     {
848         SetLastError(ERROR_OUTOFMEMORY);
849         goto done;
850     }
851     current_resource->wLanguage = wLanguage;
852     memcpy(current_resource->lpData, lpData, cbData);
853     current_resource->lpData = lpData;
854     current_resource->cbData = cbData;
855     list_add_tail(&current_updates->resources_list, &current_resource->entry);
856     ret = TRUE;
857
858 done:
859     if(!ret && current_resource)
860     {
861         if(HIWORD(current_resource->lpType)) HeapFree(GetProcessHeap(), 0, current_resource->lpType);
862         if(HIWORD(current_resource->lpName)) HeapFree(GetProcessHeap(), 0, current_resource->lpName);
863         if(current_resource->lpData) HeapFree(GetProcessHeap(), 0, current_resource->lpData);
864         HeapFree(GetProcessHeap(), 0, current_resource);
865     }
866     if(found) GlobalUnlock(hUpdate);
867     return ret;
868 }
869
870
871 /***********************************************************************
872  *           UpdateResourceA                 (KERNEL32.@)
873  */
874 BOOL WINAPI UpdateResourceA( HANDLE hUpdate, LPCSTR lpType, LPCSTR lpName,
875                              WORD wLanguage, LPVOID lpData, DWORD cbData)
876 {
877     BOOL ret;
878     UNICODE_STRING TypeW;
879     UNICODE_STRING NameW;
880     if(!HIWORD(lpType))
881         TypeW.Buffer = (LPWSTR)lpType;
882     else
883         RtlCreateUnicodeStringFromAsciiz(&TypeW, lpType);
884     if(!HIWORD(lpName))
885         NameW.Buffer = (LPWSTR)lpName;
886     else
887         RtlCreateUnicodeStringFromAsciiz(&NameW, lpName);
888     ret = UpdateResourceW(hUpdate, TypeW.Buffer, NameW.Buffer, wLanguage, lpData, cbData);
889     if(HIWORD(lpType)) RtlFreeUnicodeString(&TypeW);
890     if(HIWORD(lpName)) RtlFreeUnicodeString(&NameW);
891     return ret;
892 }