Fix a regression in IE where the Favourites menu didn't appear
[wine/testsucceed.git] / dlls / kernel / resource.c
blobf7e5e89146a7801d0822d26de0db314e2db45234
1 /*
2 * Resources
4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995, 2003 Alexandre Julliard
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.
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.
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
22 #include "config.h"
23 #include "wine/port.h"
25 #include <stdarg.h>
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"
41 WINE_DEFAULT_DEBUG_CHANNEL(resource);
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))
50 static WINE_EXCEPTION_FILTER(page_fault)
52 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ||
53 GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION)
54 return EXCEPTION_EXECUTE_HANDLER;
55 return EXCEPTION_CONTINUE_SEARCH;
58 /* retrieve the resource name to pass to the ntdll functions */
59 static NTSTATUS get_res_nameA( LPCSTR name, UNICODE_STRING *str )
61 if (!HIWORD(name))
63 str->Buffer = (LPWSTR)name;
64 return STATUS_SUCCESS;
66 if (name[0] == '#')
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;
74 RtlCreateUnicodeStringFromAsciiz( str, name );
75 RtlUpcaseUnicodeString( str, str, FALSE );
76 return STATUS_SUCCESS;
79 /* retrieve the resource name to pass to the ntdll functions */
80 static NTSTATUS get_res_nameW( LPCWSTR name, UNICODE_STRING *str )
82 if (!HIWORD(name))
84 str->Buffer = (LPWSTR)name;
85 return STATUS_SUCCESS;
87 if (name[0] == '#')
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;
96 RtlCreateUnicodeString( str, name );
97 RtlUpcaseUnicodeString( str, str, FALSE );
98 return STATUS_SUCCESS;
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 )
104 *nameA = *typeA = NULL;
106 __TRY
108 if (HIWORD(name))
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 );
114 else *nameA = (LPSTR)name;
116 if (HIWORD(type))
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 );
122 else *typeA = (LPSTR)type;
124 __EXCEPT(page_fault)
126 if (HIWORD(*nameA)) HeapFree( GetProcessHeap(), 0, *nameA );
127 if (HIWORD(*typeA)) HeapFree( GetProcessHeap(), 0, *typeA );
128 SetLastError( ERROR_INVALID_PARAMETER );
129 return FALSE;
131 __ENDTRY
132 return TRUE;
135 /* implementation of FindResourceExA */
136 static HRSRC find_resourceA( HMODULE hModule, LPCSTR type, LPCSTR name, WORD lang )
138 NTSTATUS status;
139 UNICODE_STRING nameW, typeW;
140 LDR_RESOURCE_INFO info;
141 const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL;
143 __TRY
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) );
154 __EXCEPT(page_fault)
156 SetLastError( ERROR_INVALID_PARAMETER );
158 __ENDTRY
160 if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
161 if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
162 return (HRSRC)entry;
166 /* implementation of FindResourceExW */
167 static HRSRC find_resourceW( HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD lang )
169 NTSTATUS status;
170 UNICODE_STRING nameW, typeW;
171 LDR_RESOURCE_INFO info;
172 const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL;
174 nameW.Buffer = typeW.Buffer = NULL;
176 __TRY
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) );
187 __EXCEPT(page_fault)
189 SetLastError( ERROR_INVALID_PARAMETER );
191 __ENDTRY
193 if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
194 if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
195 return (HRSRC)entry;
198 /**********************************************************************
199 * FindResourceExA (KERNEL32.@)
201 HRSRC WINAPI FindResourceExA( HMODULE hModule, LPCSTR type, LPCSTR name, WORD lang )
203 TRACE( "%p %s %s %04x\n", hModule, debugstr_a(type), debugstr_a(name), lang );
205 if (!hModule) hModule = GetModuleHandleW(0);
206 else if (!HIWORD(hModule))
208 return HRSRC_32( FindResource16( HMODULE_16(hModule), name, type ) );
210 return find_resourceA( hModule, type, name, lang );
214 /**********************************************************************
215 * FindResourceA (KERNEL32.@)
217 HRSRC WINAPI FindResourceA( HMODULE hModule, LPCSTR name, LPCSTR type )
219 return FindResourceExA( hModule, type, name, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
223 /**********************************************************************
224 * FindResourceExW (KERNEL32.@)
226 HRSRC WINAPI FindResourceExW( HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD lang )
228 TRACE( "%p %s %s %04x\n", hModule, debugstr_w(type), debugstr_w(name), lang );
230 if (!hModule) hModule = GetModuleHandleW(0);
231 else if (!HIWORD(hModule))
233 LPSTR nameA, typeA;
234 HRSRC16 ret;
236 if (!get_res_name_type_WtoA( name, type, &nameA, &typeA )) return NULL;
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);
244 return find_resourceW( hModule, type, name, lang );
248 /**********************************************************************
249 * FindResourceW (KERNEL32.@)
251 HRSRC WINAPI FindResourceW( HINSTANCE hModule, LPCWSTR name, LPCWSTR type )
253 return FindResourceExW( hModule, type, name, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
257 /**********************************************************************
258 * EnumResourceTypesA (KERNEL32.@)
260 BOOL WINAPI EnumResourceTypesA( HMODULE hmod, ENUMRESTYPEPROCA lpfun, LONG_PTR lparam )
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;
271 TRACE( "%p %p %lx\n", hmod, lpfun, lparam );
273 if (!hmod) hmod = GetModuleHandleA( NULL );
275 if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &resdir )) != STATUS_SUCCESS)
277 SetLastError( RtlNtStatusToDosError(status) );
278 return FALSE;
280 et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
281 for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
283 if (et[i].u1.s1.NameIsString)
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)
289 len = newlen + 1;
290 HeapFree( GetProcessHeap(), 0, type );
291 if (!(type = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE;
293 WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, type, len, NULL, NULL);
294 type[newlen] = 0;
295 ret = lpfun(hmod,type,lparam);
297 else
299 ret = lpfun( hmod, (LPSTR)(int)et[i].u1.s2.Id, lparam );
301 if (!ret) break;
303 HeapFree( GetProcessHeap(), 0, type );
304 return ret;
308 /**********************************************************************
309 * EnumResourceTypesW (KERNEL32.@)
311 BOOL WINAPI EnumResourceTypesW( HMODULE hmod, ENUMRESTYPEPROCW lpfun, LONG_PTR lparam )
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;
321 TRACE( "%p %p %lx\n", hmod, lpfun, lparam );
323 if (!hmod) hmod = GetModuleHandleW( NULL );
325 if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &resdir )) != STATUS_SUCCESS)
327 SetLastError( RtlNtStatusToDosError(status) );
328 return FALSE;
330 et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
331 for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++)
333 if (et[i].u1.s1.NameIsString)
335 str = (PIMAGE_RESOURCE_DIR_STRING_U) ((LPBYTE) resdir + et[i].u1.s1.NameOffset);
336 if (str->Length + 1 > len)
338 len = str->Length + 1;
339 HeapFree( GetProcessHeap(), 0, type );
340 if (!(type = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return FALSE;
342 memcpy(type, str->NameString, str->Length * sizeof (WCHAR));
343 type[str->Length] = 0;
344 ret = lpfun(hmod,type,lparam);
346 else
348 ret = lpfun( hmod, (LPWSTR)(int)et[i].u1.s2.Id, lparam );
350 if (!ret) break;
352 HeapFree( GetProcessHeap(), 0, type );
353 return ret;
357 /**********************************************************************
358 * EnumResourceNamesA (KERNEL32.@)
360 BOOL WINAPI EnumResourceNamesA( HMODULE hmod, LPCSTR type, ENUMRESNAMEPROCA lpfun, LONG_PTR lparam )
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;
373 TRACE( "%p %s %p %lx\n", hmod, debugstr_a(type), lpfun, lparam );
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;
385 et = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1);
386 for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
388 if (et[i].u1.s1.NameIsString)
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)
394 len = newlen + 1;
395 HeapFree( GetProcessHeap(), 0, name );
396 if (!(name = HeapAlloc(GetProcessHeap(), 0, len + 1 )))
398 ret = FALSE;
399 break;
402 WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, name, len, NULL, NULL );
403 name[newlen] = 0;
404 ret = lpfun(hmod,type,name,lparam);
406 else
408 ret = lpfun( hmod, type, (LPSTR)(int)et[i].u1.s2.Id, lparam );
410 if (!ret) break;
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;
420 /**********************************************************************
421 * EnumResourceNamesW (KERNEL32.@)
423 BOOL WINAPI EnumResourceNamesW( HMODULE hmod, LPCWSTR type, ENUMRESNAMEPROCW lpfun, LONG_PTR lparam )
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;
435 TRACE( "%p %s %p %lx\n", hmod, debugstr_w(type), lpfun, lparam );
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;
447 et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
448 for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
450 if (et[i].u1.s1.NameIsString)
452 str = (IMAGE_RESOURCE_DIR_STRING_U *) ((LPBYTE) basedir + et[i].u1.s1.NameOffset);
453 if (str->Length + 1 > len)
455 len = str->Length + 1;
456 HeapFree( GetProcessHeap(), 0, name );
457 if (!(name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
459 ret = FALSE;
460 break;
463 memcpy(name, str->NameString, str->Length * sizeof (WCHAR));
464 name[str->Length] = 0;
465 ret = lpfun(hmod,type,name,lparam);
467 else
469 ret = lpfun( hmod, type, (LPWSTR)(int)et[i].u1.s2.Id, lparam );
471 if (!ret) break;
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;
481 /**********************************************************************
482 * EnumResourceLanguagesA (KERNEL32.@)
484 BOOL WINAPI EnumResourceLanguagesA( HMODULE hmod, LPCSTR type, LPCSTR name,
485 ENUMRESLANGPROCA lpfun, LONG_PTR lparam )
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;
495 TRACE( "%p %s %s %p %lx\n", hmod, debugstr_a(type), debugstr_a(name), lpfun, lparam );
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;
510 et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
511 for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++)
513 ret = lpfun( hmod, type, name, et[i].u1.s2.Id, lparam );
514 if (!ret) break;
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;
524 /**********************************************************************
525 * EnumResourceLanguagesW (KERNEL32.@)
527 BOOL WINAPI EnumResourceLanguagesW( HMODULE hmod, LPCWSTR type, LPCWSTR name,
528 ENUMRESLANGPROCW lpfun, LONG_PTR lparam )
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;
538 TRACE( "%p %s %s %p %lx\n", hmod, debugstr_w(type), debugstr_w(name), lpfun, lparam );
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;
553 et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
554 for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++)
556 ret = lpfun( hmod, type, name, et[i].u1.s2.Id, lparam );
557 if (!ret) break;
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;
567 /**********************************************************************
568 * LoadResource (KERNEL32.@)
570 HGLOBAL WINAPI LoadResource( HINSTANCE hModule, HRSRC hRsrc )
572 NTSTATUS status;
573 void *ret = NULL;
575 TRACE( "%p %p\n", hModule, hRsrc );
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) ) );
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;
589 /**********************************************************************
590 * LockResource (KERNEL32.@)
592 LPVOID WINAPI LockResource( HGLOBAL handle )
594 TRACE("(%p)\n", handle );
596 if (HIWORD( handle )) /* 32-bit memory handle */
597 return (LPVOID)handle;
599 /* 16-bit memory handle */
600 return LockResource16( HGLOBAL_16(handle) );
604 /**********************************************************************
605 * FreeResource (KERNEL32.@)
607 BOOL WINAPI FreeResource( HGLOBAL handle )
609 if (HIWORD(handle)) return 0; /* 32-bit memory handle: nothing to do */
610 return FreeResource16( HGLOBAL_16(handle) );
614 /**********************************************************************
615 * SizeofResource (KERNEL32.@)
617 DWORD WINAPI SizeofResource( HINSTANCE hModule, HRSRC hRsrc )
619 if (hModule && !HIWORD(hModule))
620 return SizeofResource16( HMODULE_16(hModule), HRSRC_16(hRsrc) );
622 if (!hRsrc) return 0;
623 return ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->Size;
627 typedef struct
629 LPWSTR pFileName;
630 struct list resources_list;
631 } QUEUEDUPDATES;
633 typedef struct
635 struct list entry;
636 LPWSTR lpType;
637 LPWSTR lpName;
638 WORD wLanguage;
639 LPVOID lpData;
640 DWORD cbData;
641 } QUEUEDRESOURCE;
643 static BOOL CALLBACK enum_resources_languages_delete_all(HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, WORD wLang, LONG_PTR lParam)
645 return UpdateResourceW((HANDLE)lParam, lpType, lpName, wLang, NULL, 0);
648 static BOOL CALLBACK enum_resources_names_delete_all(HMODULE hModule, LPCWSTR lpType, LPWSTR lpName, LONG_PTR lParam)
650 return EnumResourceLanguagesW(hModule, lpType, lpName, enum_resources_languages_delete_all, lParam);
653 static BOOL CALLBACK enum_resources_types_delete_all(HMODULE hModule, LPWSTR lpType, LONG_PTR lParam)
655 return EnumResourceNamesW(hModule, lpType, enum_resources_names_delete_all, lParam);
658 static BOOL CALLBACK enum_resources_languages_add_all(HMODULE hModule, LPCWSTR lpType, LPCWSTR lpName, WORD wLang, LONG_PTR lParam)
660 DWORD size;
661 HRSRC hResource = FindResourceExW(hModule, lpType, lpName, wLang);
662 HGLOBAL hGlobal;
663 LPVOID lpData;
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);
672 static BOOL CALLBACK enum_resources_names_add_all(HMODULE hModule, LPCWSTR lpType, LPWSTR lpName, LONG_PTR lParam)
674 return EnumResourceLanguagesW(hModule, lpType, lpName, enum_resources_languages_add_all, lParam);
677 static BOOL CALLBACK enum_resources_types_add_all(HMODULE hModule, LPWSTR lpType, LONG_PTR lParam)
679 return EnumResourceNamesW(hModule, lpType, enum_resources_names_add_all, lParam);
682 /***********************************************************************
683 * BeginUpdateResourceW (KERNEL32.@)
685 HANDLE WINAPI BeginUpdateResourceW( LPCWSTR pFileName, BOOL bDeleteExistingResources )
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;
694 TRACE("%s, %d\n",debugstr_w(pFileName),bDeleteExistingResources);
696 hFile = FindFirstFileW(pFileName, &fd);
697 if(hFile == INVALID_HANDLE_VALUE)
699 hFile = NULL;
700 SetLastError(ERROR_FILE_NOT_FOUND);
701 goto done;
703 if(fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
705 SetLastError(ERROR_FILE_READ_ONLY);
706 goto done;
709 hModule = LoadLibraryW(pFileName);
710 if(hModule == NULL)
712 SetLastError(ERROR_INVALID_PARAMETER);
713 goto done;
716 if(!(hUpdate = GlobalAlloc(GHND, sizeof(QUEUEDUPDATES))))
718 SetLastError(ERROR_OUTOFMEMORY);
719 goto done;
721 if(!(current_updates = GlobalLock(hUpdate)))
723 SetLastError(ERROR_INVALID_HANDLE);
724 goto done;
726 if(!(current_updates->pFileName = HeapAlloc(GetProcessHeap(), 0, (strlenW(pFileName)+1)*sizeof(WCHAR))))
728 SetLastError(ERROR_OUTOFMEMORY);
729 goto done;
731 strcpyW(current_updates->pFileName, pFileName);
732 list_init(&current_updates->resources_list);
734 if(bDeleteExistingResources)
736 if(!EnumResourceTypesW(hModule, enum_resources_types_delete_all, (LONG_PTR)hUpdate))
737 goto done;
739 else
741 if(!EnumResourceTypesW(hModule, enum_resources_types_add_all, (LONG_PTR)hUpdate))
742 goto done;
744 ret = hUpdate;
746 done:
747 if(!ret && current_updates)
749 HeapFree(GetProcessHeap(), 0, current_updates->pFileName);
750 GlobalUnlock(hUpdate);
751 GlobalFree(hUpdate);
752 hUpdate = NULL;
754 if(hUpdate) GlobalUnlock(hUpdate);
755 if(hModule) FreeLibrary(hModule);
756 if(hFile) FindClose(hFile);
757 return ret;
761 /***********************************************************************
762 * BeginUpdateResourceA (KERNEL32.@)
764 HANDLE WINAPI BeginUpdateResourceA( LPCSTR pFileName, BOOL bDeleteExistingResources )
766 UNICODE_STRING FileNameW;
767 HANDLE ret;
768 RtlCreateUnicodeStringFromAsciiz(&FileNameW, pFileName);
769 ret = BeginUpdateResourceW(FileNameW.Buffer, bDeleteExistingResources);
770 RtlFreeUnicodeString(&FileNameW);
771 return ret;
775 /***********************************************************************
776 * EndUpdateResourceW (KERNEL32.@)
778 BOOL WINAPI EndUpdateResourceW( HANDLE hUpdate, BOOL fDiscard )
780 QUEUEDUPDATES *current_updates = NULL;
781 BOOL found = TRUE;
782 BOOL ret = FALSE;
783 struct list *ptr = NULL;
784 QUEUEDRESOURCE *current_resource = NULL;
786 FIXME("(%p,%d): stub\n",hUpdate,fDiscard);
788 if(!(current_updates = GlobalLock(hUpdate)))
790 SetLastError(ERROR_INVALID_HANDLE);
791 found = FALSE;
792 goto done;
795 if(fDiscard)
796 ret = TRUE;
797 else
799 /* FIXME: This is the only missing part, an actual implementation */
800 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
801 ret = FALSE;
804 done:
805 if(found)
807 while ((ptr = list_head(&current_updates->resources_list)) != NULL)
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);
816 HeapFree(GetProcessHeap(), 0, current_updates->pFileName);
817 GlobalUnlock(hUpdate);
818 GlobalFree(hUpdate);
820 return ret;
824 /***********************************************************************
825 * EndUpdateResourceA (KERNEL32.@)
827 BOOL WINAPI EndUpdateResourceA( HANDLE hUpdate, BOOL fDiscard )
829 return EndUpdateResourceW(hUpdate, fDiscard);
833 /***********************************************************************
834 * UpdateResourceW (KERNEL32.@)
836 BOOL WINAPI UpdateResourceW( HANDLE hUpdate, LPCWSTR lpType, LPCWSTR lpName,
837 WORD wLanguage, LPVOID lpData, DWORD cbData)
839 QUEUEDUPDATES *current_updates = NULL;
840 BOOL found = TRUE;
841 QUEUEDRESOURCE *current_resource = NULL;
842 BOOL ret = FALSE;
844 TRACE("%p %s %s %08x %p %ld\n",hUpdate,debugstr_w(lpType),debugstr_w(lpName),wLanguage,lpData,cbData);
846 if(!(current_updates = GlobalLock(hUpdate)))
848 SetLastError(ERROR_INVALID_HANDLE);
849 found = FALSE;
850 goto done;
853 if(!(current_resource = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUEDRESOURCE))))
855 SetLastError(ERROR_OUTOFMEMORY);
856 goto done;
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
864 SetLastError(ERROR_OUTOFMEMORY);
865 goto done;
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
873 SetLastError(ERROR_OUTOFMEMORY);
874 goto done;
876 if(!(current_resource->lpData = HeapAlloc(GetProcessHeap(), 0, cbData)))
878 SetLastError(ERROR_OUTOFMEMORY);
879 goto done;
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;
887 done:
888 if(!ret && current_resource)
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);
895 if(found) GlobalUnlock(hUpdate);
896 return ret;
900 /***********************************************************************
901 * UpdateResourceA (KERNEL32.@)
903 BOOL WINAPI UpdateResourceA( HANDLE hUpdate, LPCSTR lpType, LPCSTR lpName,
904 WORD wLanguage, LPVOID lpData, DWORD cbData)
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;