Fixed regression in loading of builtin apps from the system dir when
[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
38 WINE_DEFAULT_DEBUG_CHANNEL(resource);
39
40 /* handle conversions */
41 #define HRSRC_32(h16)   ((HRSRC)(ULONG_PTR)(h16))
42 #define HRSRC_16(h32)   (LOWORD(h32))
43 #define HGLOBAL_32(h16) ((HGLOBAL)(ULONG_PTR)(h16))
44 #define HGLOBAL_16(h32) (LOWORD(h32))
45 #define HMODULE_16(h32) (LOWORD(h32))
46
47
48 /* retrieve the resource name to pass to the ntdll functions */
49 static NTSTATUS get_res_nameA( LPCSTR name, UNICODE_STRING *str )
50 {
51     if (!HIWORD(name))
52     {
53         str->Buffer = (LPWSTR)name;
54         return STATUS_SUCCESS;
55     }
56     if (name[0] == '#')
57     {
58         ULONG value;
59         if (RtlCharToInteger( name + 1, 10, &value ) != STATUS_SUCCESS || HIWORD(value))
60             return STATUS_INVALID_PARAMETER;
61         str->Buffer = (LPWSTR)value;
62         return STATUS_SUCCESS;
63     }
64     RtlCreateUnicodeStringFromAsciiz( str, name );
65     RtlUpcaseUnicodeString( str, str, FALSE );
66     return STATUS_SUCCESS;
67 }
68
69 /* retrieve the resource name to pass to the ntdll functions */
70 static NTSTATUS get_res_nameW( LPCWSTR name, UNICODE_STRING *str )
71 {
72     if (!HIWORD(name))
73     {
74         str->Buffer = (LPWSTR)name;
75         return STATUS_SUCCESS;
76     }
77     if (name[0] == '#')
78     {
79         ULONG value;
80         RtlInitUnicodeString( str, name + 1 );
81         if (RtlUnicodeStringToInteger( str, 10, &value ) != STATUS_SUCCESS || HIWORD(value))
82             return STATUS_INVALID_PARAMETER;
83         str->Buffer = (LPWSTR)value;
84         return STATUS_SUCCESS;
85     }
86     RtlCreateUnicodeString( str, name );
87     RtlUpcaseUnicodeString( str, str, FALSE );
88     return STATUS_SUCCESS;
89 }
90
91 /**********************************************************************
92  *          FindResourceExA  (KERNEL32.@)
93  */
94 HRSRC WINAPI FindResourceExA( HMODULE hModule, LPCSTR type, LPCSTR name, WORD lang )
95 {
96     NTSTATUS status;
97     UNICODE_STRING nameW, typeW;
98     LDR_RESOURCE_INFO info;
99     const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL;
100
101     TRACE( "%p %s %s %04x\n", hModule, debugstr_a(type), debugstr_a(name), lang );
102
103     if (!hModule) hModule = GetModuleHandleW(0);
104     else if (!HIWORD(hModule))
105     {
106         return HRSRC_32( FindResource16( HMODULE_16(hModule), name, type ) );
107     }
108
109     nameW.Buffer = typeW.Buffer = NULL;
110     if ((status = get_res_nameA( name, &nameW )) != STATUS_SUCCESS) goto done;
111     if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS) goto done;
112     info.Type = (ULONG)typeW.Buffer;
113     info.Name = (ULONG)nameW.Buffer;
114     info.Language = lang;
115     status = LdrFindResource_U( hModule, &info, 3, &entry );
116 done:
117     if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
118     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
119     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
120     return (HRSRC)entry;
121 }
122
123
124 /**********************************************************************
125  *          FindResourceA    (KERNEL32.@)
126  */
127 HRSRC WINAPI FindResourceA( HMODULE hModule, LPCSTR name, LPCSTR type )
128 {
129     return FindResourceExA( hModule, type, name, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
130 }
131
132
133 /**********************************************************************
134  *          FindResourceExW  (KERNEL32.@)
135  */
136 HRSRC WINAPI FindResourceExW( HMODULE hModule, LPCWSTR type, LPCWSTR 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     TRACE( "%p %s %s %04x\n", hModule, debugstr_w(type), debugstr_w(name), lang );
144
145     if (!hModule) hModule = GetModuleHandleW(0);
146     else if (!HIWORD(hModule))
147     {
148         LPSTR nameA, typeA;
149         HRSRC16 ret;
150
151         if (HIWORD(name))
152         {
153             DWORD len = WideCharToMultiByte( CP_ACP, 0, name, -1, NULL, 0, NULL, NULL );
154             nameA = HeapAlloc( GetProcessHeap(), 0, len );
155             if (nameA) WideCharToMultiByte( CP_ACP, 0, name, -1, nameA, len, NULL, NULL );
156         }
157         else nameA = (LPSTR)name;
158
159         if (HIWORD(type))
160         {
161             DWORD len = WideCharToMultiByte( CP_ACP, 0, type, -1, NULL, 0, NULL, NULL );
162             typeA = HeapAlloc( GetProcessHeap(), 0, len );
163             if (typeA) WideCharToMultiByte( CP_ACP, 0, type, -1, typeA, len, NULL, NULL );
164         }
165         else typeA = (LPSTR)type;
166
167         ret = FindResource16( HMODULE_16(hModule), nameA, typeA );
168         if (HIWORD(nameA)) HeapFree( GetProcessHeap(), 0, nameA );
169         if (HIWORD(typeA)) HeapFree( GetProcessHeap(), 0, typeA );
170         return HRSRC_32(ret);
171     }
172
173     nameW.Buffer = typeW.Buffer = NULL;
174     if ((status = get_res_nameW( name, &nameW )) != STATUS_SUCCESS) goto done;
175     if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS) goto done;
176     info.Type = (ULONG)typeW.Buffer;
177     info.Name = (ULONG)nameW.Buffer;
178     info.Language = lang;
179     status = LdrFindResource_U( hModule, &info, 3, &entry );
180 done:
181     if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
182     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
183     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
184     return (HRSRC)entry;
185 }
186
187
188 /**********************************************************************
189  *          FindResourceW    (KERNEL32.@)
190  */
191 HRSRC WINAPI FindResourceW( HINSTANCE hModule, LPCWSTR name, LPCWSTR type )
192 {
193     return FindResourceExW( hModule, type, name, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
194 }
195
196
197 /**********************************************************************
198  *      EnumResourceTypesA      (KERNEL32.@)
199  */
200 BOOL WINAPI EnumResourceTypesA( HMODULE hmod, ENUMRESTYPEPROCA lpfun, LONG_PTR lparam )
201 {
202     int i;
203     BOOL ret = FALSE;
204     LPSTR type = NULL;
205     DWORD len = 0, newlen;
206     NTSTATUS status;
207     const IMAGE_RESOURCE_DIRECTORY *resdir;
208     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
209     const IMAGE_RESOURCE_DIR_STRING_U *str;
210
211     TRACE( "%p %p %lx\n", hmod, lpfun, lparam );
212
213     if (!hmod) hmod = GetModuleHandleA( NULL );
214
215     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &resdir )) != STATUS_SUCCESS)
216     {
217         SetLastError( RtlNtStatusToDosError(status) );
218         return FALSE;
219     }
220     et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
221     for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
222     {
223         if (et[i].u1.s1.NameIsString)
224         {
225             str = (PIMAGE_RESOURCE_DIR_STRING_U) ((LPBYTE) resdir + et[i].u1.s1.NameOffset);
226             newlen = WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, NULL, 0, NULL, NULL);
227             if (newlen + 1 > len)
228             {
229                 len = newlen + 1;
230                 if (type) HeapFree( GetProcessHeap(), 0, type );
231                 if (!(type = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE;
232             }
233             WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, type, len, NULL, NULL);
234             type[newlen] = 0;
235             ret = lpfun(hmod,type,lparam);
236         }
237         else
238         {
239             ret = lpfun( hmod, (LPSTR)(int)et[i].u1.s2.Id, lparam );
240         }
241         if (!ret) break;
242     }
243     if (type) HeapFree( GetProcessHeap(), 0, type );
244     return ret;
245 }
246
247
248 /**********************************************************************
249  *      EnumResourceTypesW      (KERNEL32.@)
250  */
251 BOOL WINAPI EnumResourceTypesW( HMODULE hmod, ENUMRESTYPEPROCW lpfun, LONG_PTR lparam )
252 {
253     int i;
254     BOOL ret = FALSE;
255     DWORD len = 0;
256     LPWSTR type = NULL;
257     NTSTATUS status;
258     const IMAGE_RESOURCE_DIRECTORY *resdir;
259     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
260     const IMAGE_RESOURCE_DIR_STRING_U *str;
261
262     TRACE( "%p %p %lx\n", hmod, lpfun, lparam );
263
264     if (!hmod) hmod = GetModuleHandleW( NULL );
265
266     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &resdir )) != STATUS_SUCCESS)
267     {
268         SetLastError( RtlNtStatusToDosError(status) );
269         return FALSE;
270     }
271     et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
272     for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++)
273     {
274         if (et[i].u1.s1.NameIsString)
275         {
276             str = (PIMAGE_RESOURCE_DIR_STRING_U) ((LPBYTE) resdir + et[i].u1.s1.NameOffset);
277             if (str->Length + 1 > len)
278             {
279                 len = str->Length + 1;
280                 if (type) HeapFree( GetProcessHeap(), 0, type );
281                 if (!(type = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return FALSE;
282             }
283             memcpy(type, str->NameString, str->Length * sizeof (WCHAR));
284             type[str->Length] = 0;
285             ret = lpfun(hmod,type,lparam);
286         }
287         else
288         {
289             ret = lpfun( hmod, (LPWSTR)(int)et[i].u1.s2.Id, lparam );
290         }
291         if (!ret) break;
292     }
293     if (type) HeapFree( GetProcessHeap(), 0, type );
294     return ret;
295 }
296
297
298 /**********************************************************************
299  *      EnumResourceNamesA      (KERNEL32.@)
300  */
301 BOOL WINAPI EnumResourceNamesA( HMODULE hmod, LPCSTR type, ENUMRESNAMEPROCA lpfun, LONG_PTR lparam )
302 {
303     int i;
304     BOOL ret = FALSE;
305     DWORD len = 0, newlen;
306     LPSTR name = NULL;
307     NTSTATUS status;
308     UNICODE_STRING typeW;
309     LDR_RESOURCE_INFO info;
310     const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir;
311     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
312     const IMAGE_RESOURCE_DIR_STRING_U *str;
313
314     TRACE( "%p %s %p %lx\n", hmod, debugstr_a(type), lpfun, lparam );
315
316     if (!hmod) hmod = GetModuleHandleA( NULL );
317     typeW.Buffer = NULL;
318     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
319         goto done;
320     if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS)
321         goto done;
322     info.Type = (ULONG)typeW.Buffer;
323     if ((status = LdrFindResourceDirectory_U( hmod, &info, 1, &resdir )) != STATUS_SUCCESS)
324         goto done;
325
326     et = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1);
327     for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
328     {
329         if (et[i].u1.s1.NameIsString)
330         {
331             str = (IMAGE_RESOURCE_DIR_STRING_U *) ((LPBYTE) basedir + et[i].u1.s1.NameOffset);
332             newlen = WideCharToMultiByte(CP_ACP, 0, str->NameString, str->Length, NULL, 0, NULL, NULL);
333             if (newlen + 1 > len)
334             {
335                 len = newlen + 1;
336                 if (name) HeapFree( GetProcessHeap(), 0, name );
337                 if (!(name = HeapAlloc(GetProcessHeap(), 0, len + 1 )))
338                 {
339                     ret = FALSE;
340                     break;
341                 }
342             }
343             WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, name, len, NULL, NULL );
344             name[newlen] = 0;
345             ret = lpfun(hmod,type,name,lparam);
346         }
347         else
348         {
349             ret = lpfun( hmod, type, (LPSTR)(int)et[i].u1.s2.Id, lparam );
350         }
351         if (!ret) break;
352     }
353 done:
354     if (name) HeapFree( GetProcessHeap(), 0, name );
355     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
356     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
357     return ret;
358 }
359
360
361 /**********************************************************************
362  *      EnumResourceNamesW      (KERNEL32.@)
363  */
364 BOOL WINAPI EnumResourceNamesW( HMODULE hmod, LPCWSTR type, ENUMRESNAMEPROCW lpfun, LONG_PTR lparam )
365 {
366     int i;
367     BOOL ret = FALSE;
368     LPWSTR name = NULL;
369     DWORD len = 0;
370     NTSTATUS status;
371     UNICODE_STRING typeW;
372     LDR_RESOURCE_INFO info;
373     const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir;
374     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
375     const IMAGE_RESOURCE_DIR_STRING_U *str;
376
377     TRACE( "%p %s %p %lx\n", hmod, debugstr_w(type), lpfun, lparam );
378
379     if (!hmod) hmod = GetModuleHandleW( NULL );
380     typeW.Buffer = NULL;
381     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
382         goto done;
383     if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS)
384         goto done;
385     info.Type = (ULONG)typeW.Buffer;
386     if ((status = LdrFindResourceDirectory_U( hmod, &info, 1, &resdir )) != STATUS_SUCCESS)
387         goto done;
388
389     et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
390     for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
391     {
392         if (et[i].u1.s1.NameIsString)
393         {
394             str = (IMAGE_RESOURCE_DIR_STRING_U *) ((LPBYTE) basedir + et[i].u1.s1.NameOffset);
395             if (str->Length + 1 > len)
396             {
397                 len = str->Length + 1;
398                 if (name) HeapFree( GetProcessHeap(), 0, name );
399                 if (!(name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
400                 {
401                     ret = FALSE;
402                     break;
403                 }
404             }
405             memcpy(name, str->NameString, str->Length * sizeof (WCHAR));
406             name[str->Length] = 0;
407             ret = lpfun(hmod,type,name,lparam);
408         }
409         else
410         {
411             ret = lpfun( hmod, type, (LPWSTR)(int)et[i].u1.s2.Id, lparam );
412         }
413         if (!ret) break;
414     }
415 done:
416     if (name) HeapFree( GetProcessHeap(), 0, name );
417     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
418     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
419     return ret;
420 }
421
422
423 /**********************************************************************
424  *      EnumResourceLanguagesA  (KERNEL32.@)
425  */
426 BOOL WINAPI EnumResourceLanguagesA( HMODULE hmod, LPCSTR type, LPCSTR name,
427                                     ENUMRESLANGPROCA lpfun, LONG_PTR lparam )
428 {
429     int i;
430     BOOL ret = FALSE;
431     NTSTATUS status;
432     UNICODE_STRING typeW, nameW;
433     LDR_RESOURCE_INFO info;
434     const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir;
435     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
436
437     TRACE( "%p %s %s %p %lx\n", hmod, debugstr_a(type), debugstr_a(name), lpfun, lparam );
438
439     if (!hmod) hmod = GetModuleHandleA( NULL );
440     typeW.Buffer = nameW.Buffer = NULL;
441     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
442         goto done;
443     if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS)
444         goto done;
445     if ((status = get_res_nameA( name, &nameW )) != STATUS_SUCCESS)
446         goto done;
447     info.Type = (ULONG)typeW.Buffer;
448     info.Name = (ULONG)nameW.Buffer;
449     if ((status = LdrFindResourceDirectory_U( hmod, &info, 2, &resdir )) != STATUS_SUCCESS)
450         goto done;
451
452     et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
453     for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++)
454     {
455         ret = lpfun( hmod, type, name, et[i].u1.s2.Id, lparam );
456         if (!ret) break;
457     }
458 done:
459     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
460     if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
461     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
462     return ret;
463 }
464
465
466 /**********************************************************************
467  *      EnumResourceLanguagesW  (KERNEL32.@)
468  */
469 BOOL WINAPI EnumResourceLanguagesW( HMODULE hmod, LPCWSTR type, LPCWSTR name,
470                                     ENUMRESLANGPROCW lpfun, LONG_PTR lparam )
471 {
472     int i;
473     BOOL ret = FALSE;
474     NTSTATUS status;
475     UNICODE_STRING typeW, nameW;
476     LDR_RESOURCE_INFO info;
477     const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir;
478     const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
479
480     TRACE( "%p %s %s %p %lx\n", hmod, debugstr_w(type), debugstr_w(name), lpfun, lparam );
481
482     if (!hmod) hmod = GetModuleHandleW( NULL );
483     typeW.Buffer = nameW.Buffer = NULL;
484     if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
485         goto done;
486     if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS)
487         goto done;
488     if ((status = get_res_nameW( name, &nameW )) != STATUS_SUCCESS)
489         goto done;
490     info.Type = (ULONG)typeW.Buffer;
491     info.Name = (ULONG)nameW.Buffer;
492     if ((status = LdrFindResourceDirectory_U( hmod, &info, 2, &resdir )) != STATUS_SUCCESS)
493         goto done;
494
495     et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
496     for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++)
497     {
498         ret = lpfun( hmod, type, name, et[i].u1.s2.Id, lparam );
499         if (!ret) break;
500     }
501 done:
502     if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
503     if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
504     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
505     return ret;
506 }
507
508
509 /**********************************************************************
510  *          LoadResource     (KERNEL32.@)
511  */
512 HGLOBAL WINAPI LoadResource( HINSTANCE hModule, HRSRC hRsrc )
513 {
514     NTSTATUS status;
515     void *ret = NULL;
516
517     TRACE( "%p %p\n", hModule, hRsrc );
518
519     if (hModule && !HIWORD(hModule))
520         /* FIXME: should convert return to 32-bit resource */
521         return HGLOBAL_32( LoadResource16( HMODULE_16(hModule), HRSRC_16(hRsrc) ) );
522
523     if (!hRsrc) return 0;
524     if (!hModule) hModule = GetModuleHandleA( NULL );
525     status = LdrAccessResource( hModule, (IMAGE_RESOURCE_DATA_ENTRY *)hRsrc, &ret, NULL );
526     if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
527     return ret;
528 }
529
530
531 /**********************************************************************
532  *          LockResource     (KERNEL32.@)
533  */
534 LPVOID WINAPI LockResource( HGLOBAL handle )
535 {
536     TRACE("(%p)\n", handle );
537
538     if (HIWORD( handle ))  /* 32-bit memory handle */
539         return (LPVOID)handle;
540
541     /* 16-bit memory handle */
542     return LockResource16( HGLOBAL_16(handle) );
543 }
544
545
546 /**********************************************************************
547  *          FreeResource     (KERNEL32.@)
548  */
549 BOOL WINAPI FreeResource( HGLOBAL handle )
550 {
551     if (HIWORD(handle)) return 0; /* 32-bit memory handle: nothing to do */
552     return FreeResource16( HGLOBAL_16(handle) );
553 }
554
555
556 /**********************************************************************
557  *          SizeofResource   (KERNEL32.@)
558  */
559 DWORD WINAPI SizeofResource( HINSTANCE hModule, HRSRC hRsrc )
560 {
561     if (hModule && !HIWORD(hModule))
562         return SizeofResource16( HMODULE_16(hModule), HRSRC_16(hRsrc) );
563
564     if (!hRsrc) return 0;
565     return ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->Size;
566 }
567
568
569 /***********************************************************************
570  *          BeginUpdateResourceA                 (KERNEL32.@)
571  */
572 HANDLE WINAPI BeginUpdateResourceA( LPCSTR pFileName, BOOL bDeleteExistingResources )
573 {
574   FIXME("(%s,%d): stub\n",debugstr_a(pFileName),bDeleteExistingResources);
575   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
576   return 0;
577 }
578
579
580 /***********************************************************************
581  *          BeginUpdateResourceW                 (KERNEL32.@)
582  */
583 HANDLE WINAPI BeginUpdateResourceW( LPCWSTR pFileName, BOOL bDeleteExistingResources )
584 {
585   FIXME("(%s,%d): stub\n",debugstr_w(pFileName),bDeleteExistingResources);
586   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
587   return 0;
588 }
589
590
591 /***********************************************************************
592  *          EndUpdateResourceA                 (KERNEL32.@)
593  */
594 BOOL WINAPI EndUpdateResourceA( HANDLE hUpdate, BOOL fDiscard )
595 {
596   FIXME("(%p,%d): stub\n",hUpdate, fDiscard);
597   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
598   return FALSE;
599 }
600
601
602 /***********************************************************************
603  *          EndUpdateResourceW                 (KERNEL32.@)
604  */
605 BOOL WINAPI EndUpdateResourceW( HANDLE hUpdate, BOOL fDiscard )
606 {
607   FIXME("(%p,%d): stub\n",hUpdate, fDiscard);
608   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
609   return FALSE;
610 }
611
612
613 /***********************************************************************
614  *           UpdateResourceA                 (KERNEL32.@)
615  */
616 BOOL WINAPI UpdateResourceA(
617   HANDLE  hUpdate,
618   LPCSTR  lpType,
619   LPCSTR  lpName,
620   WORD    wLanguage,
621   LPVOID  lpData,
622   DWORD   cbData)
623 {
624   FIXME(": stub\n");
625   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
626   return FALSE;
627 }
628
629
630 /***********************************************************************
631  *           UpdateResourceW                 (KERNEL32.@)
632  */
633 BOOL WINAPI UpdateResourceW(
634   HANDLE  hUpdate,
635   LPCWSTR lpType,
636   LPCWSTR lpName,
637   WORD    wLanguage,
638   LPVOID  lpData,
639   DWORD   cbData)
640 {
641   FIXME(": stub\n");
642   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
643   return FALSE;
644 }