Implement {Start,End}DocPrinter and WritePrinter.
[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 "winternl.h"
33 #include "wownt32.h"
34 #include "wine/winbase16.h"
35 #include "wine/debug.h"
36 #include "excpt.h"
37 #include "wine/exception.h"
38 #include "wine/unicode.h"
39 #include "wine/list.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(resource);
42
43 /* handle conversions */
44 #define HRSRC_32(h16)   ((HRSRC)(ULONG_PTR)(h16))
45 #define HRSRC_16(h32)   (LOWORD(h32))
46 #define HGLOBAL_32(h16) ((HGLOBAL)(ULONG_PTR)(h16))
47 #define HGLOBAL_16(h32) (LOWORD(h32))
48 #define HMODULE_16(h32) (LOWORD(h32))
49
50 static WINE_EXCEPTION_FILTER(page_fault)
51 {
52     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ||
53         GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION)
54         return EXCEPTION_EXECUTE_HANDLER;
55     return EXCEPTION_CONTINUE_SEARCH;
56 }
57
58 /* retrieve the resource name to pass to the ntdll functions */
59 static NTSTATUS get_res_nameA( LPCSTR name, UNICODE_STRING *str )
60 {
61     if (!HIWORD(name))
62     {
63         str->Buffer = (LPWSTR)name;
64         return STATUS_SUCCESS;
65     }
66     if (name[0] == '#')
67     {
68         ULONG value;
69         if (RtlCharToInteger( name + 1, 10, &value ) != STATUS_SUCCESS || HIWORD(value))
70             return STATUS_INVALID_PARAMETER;
71         str->Buffer = (LPWSTR)value;
72         return STATUS_SUCCESS;
73     }
74     RtlCreateUnicodeStringFromAsciiz( str, name );
75     RtlUpcaseUnicodeString( str, str, FALSE );
76     return STATUS_SUCCESS;
77 }
78
79 /* retrieve the resource name to pass to the ntdll functions */
80 static NTSTATUS get_res_nameW( LPCWSTR name, UNICODE_STRING *str )
81 {
82     if (!HIWORD(name))
83     {
84         str->Buffer = (LPWSTR)name;
85         return STATUS_SUCCESS;
86     }
87     if (name[0] == '#')
88     {
89         ULONG value;
90         RtlInitUnicodeString( str, name + 1 );
91         if (RtlUnicodeStringToInteger( str, 10, &value ) != STATUS_SUCCESS || HIWORD(value))
92             return STATUS_INVALID_PARAMETER;
93         str->Buffer = (LPWSTR)value;
94         return STATUS_SUCCESS;
95     }
96     RtlCreateUnicodeString( str, name );
97     RtlUpcaseUnicodeString( str, str, FALSE );
98     return STATUS_SUCCESS;
99 }
100
101 /* retrieve the resource names for the 16-bit FindResource function */
102 static BOOL get_res_name_type_WtoA( LPCWSTR name, LPCWSTR type, LPSTR *nameA, LPSTR *typeA )
103 {
104     *nameA = *typeA = NULL;
105
106     __TRY
107     {
108         if (HIWORD(name))
109         {
110             DWORD len = WideCharToMultiByte( CP_ACP, 0, name, -1, NULL, 0, NULL, NULL );
111             *nameA = HeapAlloc( GetProcessHeap(), 0, len );
112             if (*nameA) WideCharToMultiByte( CP_ACP, 0, name, -1, *nameA, len, NULL, NULL );
113         }
114         else *nameA = (LPSTR)name;
115
116         if (HIWORD(type))
117         {
118             DWORD len = WideCharToMultiByte( CP_ACP, 0, type, -1, NULL, 0, NULL, NULL );
119             *typeA = HeapAlloc( GetProcessHeap(), 0, len );
120             if (*typeA) WideCharToMultiByte( CP_ACP, 0, type, -1, *typeA, len, NULL, NULL );
121         }
122         else *typeA = (LPSTR)type;
123     }
124     __EXCEPT(page_fault)
125     {
126         if (HIWORD(*nameA)) HeapFree( GetProcessHeap(), 0, *nameA );
127         if (HIWORD(*typeA)) HeapFree( GetProcessHeap(), 0, *typeA );
128         SetLastError( ERROR_INVALID_PARAMETER );
129         return FALSE;
130     }
131     __ENDTRY
132     return TRUE;
133 }
134
135 /* implementation of FindResourceExA */
136 static HRSRC find_resourceA( HMODULE hModule, LPCSTR type, LPCSTR name, WORD lang )
137 {
138     NTSTATUS status;
139     UNICODE_STRING nameW, typeW;
140     LDR_RESOURCE_INFO info;
141     const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL;
142
143     __TRY
144     {
145         if ((status = get_res_nameA( name, &nameW )) != STATUS_SUCCESS) goto done;
146         if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS) goto done;
147         info.Type = (ULONG)typeW.Buffer;
148         info.Name = (ULONG)nameW.Buffer;
149         info.Language = lang;
150         status = LdrFindResource_U( hModule, &info, 3, &entry );
151     done:
152         if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
153     }
154     __EXCEPT(page_fault)
155     {
156         SetLastError( ERROR_INVALID_PARAMETER );
157     }
158     __ENDTRY
159
160     if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
161     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
162     return (HRSRC)entry;
163 }
164
165
166 /* implementation of FindResourceExW */
167 static HRSRC find_resourceW( HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD lang )
168 {
169     NTSTATUS status;
170     UNICODE_STRING nameW, typeW;
171     LDR_RESOURCE_INFO info;
172     const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL;
173
174     nameW.Buffer = typeW.Buffer = NULL;
175
176     __TRY
177     {
178         if ((status = get_res_nameW( name, &nameW )) != STATUS_SUCCESS) goto done;
179         if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS) goto done;
180         info.Type = (ULONG)typeW.Buffer;
181         info.Name = (ULONG)nameW.Buffer;
182         info.Language = lang;
183         status = LdrFindResource_U( hModule, &info, 3, &entry );
184     done:
185         if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
186     }
187     __EXCEPT(page_fault)
188     {
189         SetLastError( ERROR_INVALID_PARAMETER );
190     }
191     __ENDTRY
192
193     if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
194     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
195     return (HRSRC)entry;
196 }
197
198 /**********************************************************************
199  *          FindResourceExA  (KERNEL32.@)
200  */
201 HRSRC WINAPI FindResourceExA( HMODULE hModule, LPCSTR type, LPCSTR name, WORD lang )
202 {
203     TRACE( "%p %s %s %04x\n", hModule, debugstr_a(type), debugstr_a(name), lang );
204
205     if (!hModule) hModule = GetModuleHandleW(0);
206     else if (!HIWORD(hModule))
207     {
208         return HRSRC_32( FindResource16( HMODULE_16(hModule), name, type ) );
209     }
210     return find_resourceA( hModule, type, name, lang );
211 }
212
213
214 /**********************************************************************
215  *          FindResourceA    (KERNEL32.@)
216  */
217 HRSRC WINAPI FindResourceA( HMODULE hModule, LPCSTR name, LPCSTR type )
218 {
219     return FindResourceExA( hModule, type, name, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
220 }
221
222
223 /**********************************************************************
224  *          FindResourceExW  (KERNEL32.@)
225  */
226 HRSRC WINAPI FindResourceExW( HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD lang )
227 {
228     TRACE( "%p %s %s %04x\n", hModule, debugstr_w(type), debugstr_w(name), lang );
229
230     if (!hModule) hModule = GetModuleHandleW(0);
231     else if (!HIWORD(hModule))
232     {
233         LPSTR nameA, typeA;
234         HRSRC16 ret;
235
236         if (!get_res_name_type_WtoA( name, type, &nameA, &typeA )) return NULL;
237
238         ret = FindResource16( HMODULE_16(hModule), nameA, typeA );
239         if (HIWORD(nameA)) HeapFree( GetProcessHeap(), 0, nameA );
240         if (HIWORD(typeA)) HeapFree( GetProcessHeap(), 0, typeA );
241         return HRSRC_32(ret);
242     }
243
244     return find_resourceW( hModule, type, name, lang );
245 }
246
247
248 /**********************************************************************
249  *          FindResourceW    (KERNEL32.@)
250  */
251 HRSRC WINAPI FindResourceW( HINSTANCE hModule, LPCWSTR name, LPCWSTR type )
252 {
253     return FindResourceExW( hModule, type, name, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
254 }
255
256
257 /**********************************************************************
258  *      EnumResourceTypesA      (KERNEL32.@)
259  */
260 BOOL WINAPI EnumResourceTypesA( HMODULE hmod, ENUMRESTYPEPROCA lpfun, LONG_PTR lparam )
261 {
262     int i;
263     BOOL ret = FALSE;
264     LPSTR type = NULL;
265     DWORD len = 0, newlen;
266     NTSTATUS status;
267     const IMAGE_RESOURCE_DIRECTORY *resdir;
268     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
269     const IMAGE_RESOURCE_DIR_STRING_U *str;
270
271     TRACE( "%p %p %lx\n", hmod, lpfun, lparam );
272
273     if (!hmod) hmod = GetModuleHandleA( NULL );
274
275     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &resdir )) != STATUS_SUCCESS)
276     {
277         SetLastError( RtlNtStatusToDosError(status) );
278         return FALSE;
279     }
280     et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
281     for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
282     {
283         if (et[i].u1.s1.NameIsString)
284         {
285             str = (PIMAGE_RESOURCE_DIR_STRING_U) ((LPBYTE) resdir + et[i].u1.s1.NameOffset);
286             newlen = WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, NULL, 0, NULL, NULL);
287             if (newlen + 1 > len)
288             {
289                 len = newlen + 1;
290                 HeapFree( GetProcessHeap(), 0, type );
291                 if (!(type = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE;
292             }
293             WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, type, len, NULL, NULL);
294             type[newlen] = 0;
295             ret = lpfun(hmod,type,lparam);
296         }
297         else
298         {
299             ret = lpfun( hmod, (LPSTR)(int)et[i].u1.s2.Id, lparam );
300         }
301         if (!ret) break;
302     }
303     HeapFree( GetProcessHeap(), 0, type );
304     return ret;
305 }
306
307
308 /**********************************************************************
309  *      EnumResourceTypesW      (KERNEL32.@)
310  */
311 BOOL WINAPI EnumResourceTypesW( HMODULE hmod, ENUMRESTYPEPROCW lpfun, LONG_PTR lparam )
312 {
313     int i, len = 0;
314     BOOL ret = FALSE;
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                 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     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                 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     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, len = 0;
426     BOOL ret = FALSE;
427     LPWSTR name = NULL;
428     NTSTATUS status;
429     UNICODE_STRING typeW;
430     LDR_RESOURCE_INFO info;
431     const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir;
432     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
433     const IMAGE_RESOURCE_DIR_STRING_U *str;
434
435     TRACE( "%p %s %p %lx\n", hmod, debugstr_w(type), lpfun, lparam );
436
437     if (!hmod) hmod = GetModuleHandleW( NULL );
438     typeW.Buffer = NULL;
439     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
440         goto done;
441     if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS)
442         goto done;
443     info.Type = (ULONG)typeW.Buffer;
444     if ((status = LdrFindResourceDirectory_U( hmod, &info, 1, &resdir )) != STATUS_SUCCESS)
445         goto done;
446
447     et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
448     for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
449     {
450         if (et[i].u1.s1.NameIsString)
451         {
452             str = (IMAGE_RESOURCE_DIR_STRING_U *) ((LPBYTE) basedir + et[i].u1.s1.NameOffset);
453             if (str->Length + 1 > len)
454             {
455                 len = str->Length + 1;
456                 HeapFree( GetProcessHeap(), 0, name );
457                 if (!(name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
458                 {
459                     ret = FALSE;
460                     break;
461                 }
462             }
463             memcpy(name, str->NameString, str->Length * sizeof (WCHAR));
464             name[str->Length] = 0;
465             ret = lpfun(hmod,type,name,lparam);
466         }
467         else
468         {
469             ret = lpfun( hmod, type, (LPWSTR)(int)et[i].u1.s2.Id, lparam );
470         }
471         if (!ret) break;
472     }
473 done:
474     HeapFree( GetProcessHeap(), 0, name );
475     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
476     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
477     return ret;
478 }
479
480
481 /**********************************************************************
482  *      EnumResourceLanguagesA  (KERNEL32.@)
483  */
484 BOOL WINAPI EnumResourceLanguagesA( HMODULE hmod, LPCSTR type, LPCSTR name,
485                                     ENUMRESLANGPROCA lpfun, LONG_PTR lparam )
486 {
487     int i;
488     BOOL ret = FALSE;
489     NTSTATUS status;
490     UNICODE_STRING typeW, nameW;
491     LDR_RESOURCE_INFO info;
492     const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir;
493     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
494
495     TRACE( "%p %s %s %p %lx\n", hmod, debugstr_a(type), debugstr_a(name), lpfun, lparam );
496
497     if (!hmod) hmod = GetModuleHandleA( NULL );
498     typeW.Buffer = nameW.Buffer = NULL;
499     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
500         goto done;
501     if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS)
502         goto done;
503     if ((status = get_res_nameA( name, &nameW )) != STATUS_SUCCESS)
504         goto done;
505     info.Type = (ULONG)typeW.Buffer;
506     info.Name = (ULONG)nameW.Buffer;
507     if ((status = LdrFindResourceDirectory_U( hmod, &info, 2, &resdir )) != STATUS_SUCCESS)
508         goto done;
509
510     et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
511     for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++)
512     {
513         ret = lpfun( hmod, type, name, et[i].u1.s2.Id, lparam );
514         if (!ret) break;
515     }
516 done:
517     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
518     if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
519     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
520     return ret;
521 }
522
523
524 /**********************************************************************
525  *      EnumResourceLanguagesW  (KERNEL32.@)
526  */
527 BOOL WINAPI EnumResourceLanguagesW( HMODULE hmod, LPCWSTR type, LPCWSTR name,
528                                     ENUMRESLANGPROCW lpfun, LONG_PTR lparam )
529 {
530     int i;
531     BOOL ret = FALSE;
532     NTSTATUS status;
533     UNICODE_STRING typeW, nameW;
534     LDR_RESOURCE_INFO info;
535     const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir;
536     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
537
538     TRACE( "%p %s %s %p %lx\n", hmod, debugstr_w(type), debugstr_w(name), lpfun, lparam );
539
540     if (!hmod) hmod = GetModuleHandleW( NULL );
541     typeW.Buffer = nameW.Buffer = NULL;
542     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
543         goto done;
544     if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS)
545         goto done;
546     if ((status = get_res_nameW( name, &nameW )) != STATUS_SUCCESS)
547         goto done;
548     info.Type = (ULONG)typeW.Buffer;
549     info.Name = (ULONG)nameW.Buffer;
550     if ((status = LdrFindResourceDirectory_U( hmod, &info, 2, &resdir )) != STATUS_SUCCESS)
551         goto done;
552
553     et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
554     for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++)
555     {
556         ret = lpfun( hmod, type, name, et[i].u1.s2.Id, lparam );
557         if (!ret) break;
558     }
559 done:
560     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
561     if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
562     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
563     return ret;
564 }
565
566
567 /**********************************************************************
568  *          LoadResource     (KERNEL32.@)
569  */
570 HGLOBAL WINAPI LoadResource( HINSTANCE hModule, HRSRC hRsrc )
571 {
572     NTSTATUS status;
573     void *ret = NULL;
574
575     TRACE( "%p %p\n", hModule, hRsrc );
576
577     if (hModule && !HIWORD(hModule))
578         /* FIXME: should convert return to 32-bit resource */
579         return HGLOBAL_32( LoadResource16( HMODULE_16(hModule), HRSRC_16(hRsrc) ) );
580
581     if (!hRsrc) return 0;
582     if (!hModule) hModule = GetModuleHandleA( NULL );
583     status = LdrAccessResource( hModule, (IMAGE_RESOURCE_DATA_ENTRY *)hRsrc, &ret, NULL );
584     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
585     return ret;
586 }
587
588
589 /**********************************************************************
590  *          LockResource     (KERNEL32.@)
591  */
592 LPVOID WINAPI LockResource( HGLOBAL handle )
593 {
594     TRACE("(%p)\n", handle );
595
596     if (HIWORD( handle ))  /* 32-bit memory handle */
597         return (LPVOID)handle;
598
599     /* 16-bit memory handle */
600     return LockResource16( HGLOBAL_16(handle) );
601 }
602
603
604 /**********************************************************************
605  *          FreeResource     (KERNEL32.@)
606  */
607 BOOL WINAPI FreeResource( HGLOBAL handle )
608 {
609     if (HIWORD(handle)) return 0; /* 32-bit memory handle: nothing to do */
610     return FreeResource16( HGLOBAL_16(handle) );
611 }
612
613
614 /**********************************************************************
615  *          SizeofResource   (KERNEL32.@)
616  */
617 DWORD WINAPI SizeofResource( HINSTANCE hModule, HRSRC hRsrc )
618 {
619     if (hModule && !HIWORD(hModule))
620         return SizeofResource16( HMODULE_16(hModule), HRSRC_16(hRsrc) );
621
622     if (!hRsrc) return 0;
623     return ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->Size;
624 }
625
626
627 typedef struct
628 {
629     LPWSTR pFileName;
630     struct list resources_list;
631 } QUEUEDUPDATES;
632
633 typedef struct
634 {
635     struct list entry;
636     LPWSTR lpType;
637     LPWSTR lpName;
638     WORD wLanguage;
639     LPVOID lpData;
640     DWORD cbData;
641 } QUEUEDRESOURCE;
642
643 static BOOL CALLBACK enum_resources_languages_delete_all(HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, WORD wLang, LONG_PTR lParam)
644 {
645     return UpdateResourceW((HANDLE)lParam, lpType, lpName, wLang, NULL, 0);
646 }
647
648 static BOOL CALLBACK enum_resources_names_delete_all(HMODULE hModule, LPCWSTR lpType, LPWSTR lpName, LONG_PTR lParam)
649 {
650     return EnumResourceLanguagesW(hModule, lpType, lpName, enum_resources_languages_delete_all, lParam);
651 }
652
653 static BOOL CALLBACK enum_resources_types_delete_all(HMODULE hModule, LPWSTR lpType, LONG_PTR lParam)
654 {
655     return EnumResourceNamesW(hModule, lpType, enum_resources_names_delete_all, lParam);
656 }
657
658 static BOOL CALLBACK enum_resources_languages_add_all(HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, WORD wLang, LONG_PTR lParam)
659 {
660     DWORD size;
661     HRSRC hResource = FindResourceExW(hModule, lpType, lpName, wLang);
662     HGLOBAL hGlobal;
663     LPVOID lpData;
664
665     if(hResource == NULL) return FALSE;
666     if(!(hGlobal = LoadResource(hModule, hResource))) return FALSE;
667     if(!(lpData = LockResource(hGlobal))) return FALSE;
668     if(!(size = SizeofResource(hModule, hResource))) return FALSE;
669     return UpdateResourceW((HANDLE)lParam, lpType, lpName, wLang, lpData, size);
670 }
671
672 static BOOL CALLBACK enum_resources_names_add_all(HMODULE hModule, LPCWSTR lpType, LPWSTR lpName, LONG_PTR lParam)
673 {
674     return EnumResourceLanguagesW(hModule, lpType, lpName, enum_resources_languages_add_all, lParam);
675 }
676
677 static BOOL CALLBACK enum_resources_types_add_all(HMODULE hModule, LPWSTR lpType, LONG_PTR lParam)
678 {
679     return EnumResourceNamesW(hModule, lpType, enum_resources_names_add_all, lParam);
680 }
681
682 /***********************************************************************
683  *          BeginUpdateResourceW                 (KERNEL32.@)
684  */
685 HANDLE WINAPI BeginUpdateResourceW( LPCWSTR pFileName, BOOL bDeleteExistingResources )
686 {
687     HANDLE hFile = NULL;
688     WIN32_FIND_DATAW fd;
689     HANDLE hModule = NULL;
690     HANDLE hUpdate = NULL;
691     QUEUEDUPDATES *current_updates = NULL;
692     HANDLE ret = NULL;
693
694     TRACE("%s, %d\n",debugstr_w(pFileName),bDeleteExistingResources);
695
696     hFile = FindFirstFileW(pFileName, &fd);
697     if(hFile == INVALID_HANDLE_VALUE)
698     {
699         hFile = NULL;
700         SetLastError(ERROR_FILE_NOT_FOUND);
701         goto done;
702     }
703     if(fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
704     {
705         SetLastError(ERROR_FILE_READ_ONLY);
706         goto done;
707     }
708
709     hModule = LoadLibraryW(pFileName);
710     if(hModule == NULL)
711     {
712         SetLastError(ERROR_INVALID_PARAMETER);
713         goto done;
714     }
715
716     if(!(hUpdate = GlobalAlloc(GHND, sizeof(QUEUEDUPDATES))))
717     {
718         SetLastError(ERROR_OUTOFMEMORY);
719         goto done;
720     }
721     if(!(current_updates = GlobalLock(hUpdate)))
722     {
723         SetLastError(ERROR_INVALID_HANDLE);
724         goto done;
725     }
726     if(!(current_updates->pFileName = HeapAlloc(GetProcessHeap(), 0, (strlenW(pFileName)+1)*sizeof(WCHAR))))
727     {
728         SetLastError(ERROR_OUTOFMEMORY);
729         goto done;
730     }
731     strcpyW(current_updates->pFileName, pFileName);
732     list_init(&current_updates->resources_list);
733
734     if(bDeleteExistingResources)
735     {
736         if(!EnumResourceTypesW(hModule, enum_resources_types_delete_all, (LONG_PTR)hUpdate))
737             goto done;
738     }
739     else
740     {
741         if(!EnumResourceTypesW(hModule, enum_resources_types_add_all, (LONG_PTR)hUpdate))
742             goto done;
743     }
744     ret = hUpdate;
745
746 done:
747     if(!ret && current_updates)
748     {
749         HeapFree(GetProcessHeap(), 0, current_updates->pFileName);
750         GlobalUnlock(hUpdate);
751         GlobalFree(hUpdate);
752         hUpdate = NULL;
753     }
754     if(hUpdate) GlobalUnlock(hUpdate);
755     if(hModule) FreeLibrary(hModule);
756     if(hFile) FindClose(hFile);
757     return ret;
758 }
759
760
761 /***********************************************************************
762  *          BeginUpdateResourceA                 (KERNEL32.@)
763  */
764 HANDLE WINAPI BeginUpdateResourceA( LPCSTR pFileName, BOOL bDeleteExistingResources )
765 {
766     UNICODE_STRING FileNameW;
767     HANDLE ret;
768     RtlCreateUnicodeStringFromAsciiz(&FileNameW, pFileName);
769     ret = BeginUpdateResourceW(FileNameW.Buffer, bDeleteExistingResources);
770     RtlFreeUnicodeString(&FileNameW);
771     return ret;
772 }
773
774
775 /***********************************************************************
776  *          EndUpdateResourceW                 (KERNEL32.@)
777  */
778 BOOL WINAPI EndUpdateResourceW( HANDLE hUpdate, BOOL fDiscard )
779 {
780     QUEUEDUPDATES *current_updates = NULL;
781     BOOL found = TRUE;
782     BOOL ret = FALSE;
783     struct list *ptr = NULL;
784     QUEUEDRESOURCE *current_resource = NULL;
785
786     FIXME("(%p,%d): stub\n",hUpdate,fDiscard);
787
788     if(!(current_updates = GlobalLock(hUpdate)))
789     {
790         SetLastError(ERROR_INVALID_HANDLE);
791         found = FALSE;
792         goto done;
793     }
794
795     if(fDiscard)
796         ret = TRUE;
797     else
798     {
799         /* FIXME: This is the only missing part, an actual implementation */
800         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
801         ret = FALSE;
802     }
803
804 done:
805     if(found)
806     {
807         while ((ptr = list_head(&current_updates->resources_list)) != NULL)
808         {
809             current_resource = LIST_ENTRY(ptr, QUEUEDRESOURCE, entry);
810             list_remove(&current_resource->entry);
811             if(HIWORD(current_resource->lpType)) HeapFree(GetProcessHeap(), 0, current_resource->lpType);
812             if(HIWORD(current_resource->lpName)) HeapFree(GetProcessHeap(), 0, current_resource->lpName);
813             HeapFree(GetProcessHeap(), 0, current_resource->lpData);
814             HeapFree(GetProcessHeap(), 0, current_resource);
815         }
816         HeapFree(GetProcessHeap(), 0, current_updates->pFileName);
817         GlobalUnlock(hUpdate);
818         GlobalFree(hUpdate);
819     }
820     return ret;
821 }
822
823
824 /***********************************************************************
825  *          EndUpdateResourceA                 (KERNEL32.@)
826  */
827 BOOL WINAPI EndUpdateResourceA( HANDLE hUpdate, BOOL fDiscard )
828 {
829     return EndUpdateResourceW(hUpdate, fDiscard);
830 }
831
832
833 /***********************************************************************
834  *           UpdateResourceW                 (KERNEL32.@)
835  */
836 BOOL WINAPI UpdateResourceW( HANDLE hUpdate, LPCWSTR lpType, LPCWSTR lpName,
837                              WORD wLanguage, LPVOID lpData, DWORD cbData)
838 {
839     QUEUEDUPDATES *current_updates = NULL;
840     BOOL found = TRUE;
841     QUEUEDRESOURCE *current_resource = NULL;
842     BOOL ret = FALSE;
843
844     TRACE("%p %s %s %08x %p %ld\n",hUpdate,debugstr_w(lpType),debugstr_w(lpName),wLanguage,lpData,cbData);
845
846     if(!(current_updates = GlobalLock(hUpdate)))
847     {
848         SetLastError(ERROR_INVALID_HANDLE);
849         found = FALSE;
850         goto done;
851     }
852
853     if(!(current_resource = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUEDRESOURCE))))
854     {
855         SetLastError(ERROR_OUTOFMEMORY);
856         goto done;
857     }
858     if(!HIWORD(lpType))
859         current_resource->lpType = (LPWSTR)lpType;
860     else if((current_resource->lpType = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpType)+1)*sizeof(WCHAR))))
861         strcpyW(current_resource->lpType, lpType);
862     else
863     {
864         SetLastError(ERROR_OUTOFMEMORY);
865         goto done;
866     }
867     if(!HIWORD(lpName))
868         current_resource->lpName = (LPWSTR)lpName;
869     else if((current_resource->lpName = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpName)+1)*sizeof(WCHAR))))
870         strcpyW(current_resource->lpName, lpName);
871     else
872     {
873         SetLastError(ERROR_OUTOFMEMORY);
874         goto done;
875     }
876     if(!(current_resource->lpData = HeapAlloc(GetProcessHeap(), 0, cbData)))
877     {
878         SetLastError(ERROR_OUTOFMEMORY);
879         goto done;
880     }
881     current_resource->wLanguage = wLanguage;
882     memcpy(current_resource->lpData, lpData, cbData);
883     current_resource->cbData = cbData;
884     list_add_tail(&current_updates->resources_list, &current_resource->entry);
885     ret = TRUE;
886
887 done:
888     if(!ret && current_resource)
889     {
890         if(HIWORD(current_resource->lpType)) HeapFree(GetProcessHeap(), 0, current_resource->lpType);
891         if(HIWORD(current_resource->lpName)) HeapFree(GetProcessHeap(), 0, current_resource->lpName);
892         HeapFree(GetProcessHeap(), 0, current_resource->lpData);
893         HeapFree(GetProcessHeap(), 0, current_resource);
894     }
895     if(found) GlobalUnlock(hUpdate);
896     return ret;
897 }
898
899
900 /***********************************************************************
901  *           UpdateResourceA                 (KERNEL32.@)
902  */
903 BOOL WINAPI UpdateResourceA( HANDLE hUpdate, LPCSTR lpType, LPCSTR lpName,
904                              WORD wLanguage, LPVOID lpData, DWORD cbData)
905 {
906     BOOL ret;
907     UNICODE_STRING TypeW;
908     UNICODE_STRING NameW;
909     if(!HIWORD(lpType))
910         TypeW.Buffer = (LPWSTR)lpType;
911     else
912         RtlCreateUnicodeStringFromAsciiz(&TypeW, lpType);
913     if(!HIWORD(lpName))
914         NameW.Buffer = (LPWSTR)lpName;
915     else
916         RtlCreateUnicodeStringFromAsciiz(&NameW, lpName);
917     ret = UpdateResourceW(hUpdate, TypeW.Buffer, NameW.Buffer, wLanguage, lpData, cbData);
918     if(HIWORD(lpType)) RtlFreeUnicodeString(&TypeW);
919     if(HIWORD(lpName)) RtlFreeUnicodeString(&NameW);
920     return ret;
921 }