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
23 #include "wine/port.h"
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
34 #include "wine/winbase16.h"
35 #include "wine/debug.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 )
63 str->Buffer = (LPWSTR)name;
64 return STATUS_SUCCESS;
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 )
84 str->Buffer = (LPWSTR)name;
85 return STATUS_SUCCESS;
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;
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;
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;
126 if (HIWORD(*nameA)) HeapFree( GetProcessHeap(), 0, *nameA );
127 if (HIWORD(*typeA)) HeapFree( GetProcessHeap(), 0, *typeA );
128 SetLastError( ERROR_INVALID_PARAMETER );
135 /* implementation of FindResourceExA */
136 static HRSRC find_resourceA( HMODULE hModule, LPCSTR type, LPCSTR name, WORD lang )
139 UNICODE_STRING nameW, typeW;
140 LDR_RESOURCE_INFO info;
141 const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL;
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 );
152 if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
156 SetLastError( ERROR_INVALID_PARAMETER );
160 if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
161 if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
166 /* implementation of FindResourceExW */
167 static HRSRC find_resourceW( HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD lang )
170 UNICODE_STRING nameW, typeW;
171 LDR_RESOURCE_INFO info;
172 const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL;
174 nameW.Buffer = typeW.Buffer = NULL;
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 );
185 if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
189 SetLastError( ERROR_INVALID_PARAMETER );
193 if (HIWORD(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer );
194 if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
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))
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 )
265 DWORD len = 0, newlen;
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) );
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)
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);
295 ret = lpfun(hmod,type,lparam);
299 ret = lpfun( hmod, (LPSTR)(int)et[i].u1.s2.Id, lparam );
303 HeapFree( GetProcessHeap(), 0, type );
308 /**********************************************************************
309 * EnumResourceTypesW (KERNEL32.@)
311 BOOL WINAPI EnumResourceTypesW( HMODULE hmod, ENUMRESTYPEPROCW lpfun, LONG_PTR lparam )
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) );
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);
348 ret = lpfun( hmod, (LPWSTR)(int)et[i].u1.s2.Id, lparam );
352 HeapFree( GetProcessHeap(), 0, type );
357 /**********************************************************************
358 * EnumResourceNamesA (KERNEL32.@)
360 BOOL WINAPI EnumResourceNamesA( HMODULE hmod, LPCSTR type, ENUMRESNAMEPROCA lpfun, LONG_PTR lparam )
364 DWORD len = 0, newlen;
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 );
377 if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
379 if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS)
381 info.Type = (ULONG)typeW.Buffer;
382 if ((status = LdrFindResourceDirectory_U( hmod, &info, 1, &resdir )) != STATUS_SUCCESS)
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)
395 HeapFree( GetProcessHeap(), 0, name );
396 if (!(name = HeapAlloc(GetProcessHeap(), 0, len + 1 )))
402 WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, name, len, NULL, NULL );
404 ret = lpfun(hmod,type,name,lparam);
408 ret = lpfun( hmod, type, (LPSTR)(int)et[i].u1.s2.Id, lparam );
413 HeapFree( GetProcessHeap(), 0, name );
414 if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
415 if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
420 /**********************************************************************
421 * EnumResourceNamesW (KERNEL32.@)
423 BOOL WINAPI EnumResourceNamesW( HMODULE hmod, LPCWSTR type, ENUMRESNAMEPROCW lpfun, LONG_PTR lparam )
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 );
439 if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
441 if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS)
443 info.Type = (ULONG)typeW.Buffer;
444 if ((status = LdrFindResourceDirectory_U( hmod, &info, 1, &resdir )) != STATUS_SUCCESS)
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) )))
463 memcpy(name, str->NameString, str->Length * sizeof (WCHAR));
464 name[str->Length] = 0;
465 ret = lpfun(hmod,type,name,lparam);
469 ret = lpfun( hmod, type, (LPWSTR)(int)et[i].u1.s2.Id, lparam );
474 HeapFree( GetProcessHeap(), 0, name );
475 if (HIWORD(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer );
476 if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) );
481 /**********************************************************************
482 * EnumResourceLanguagesA (KERNEL32.@)
484 BOOL WINAPI EnumResourceLanguagesA( HMODULE hmod, LPCSTR type, LPCSTR name,
485 ENUMRESLANGPROCA lpfun, LONG_PTR lparam )
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)
501 if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS)
503 if ((status = get_res_nameA( name, &nameW )) != STATUS_SUCCESS)
505 info.Type = (ULONG)typeW.Buffer;
506 info.Name = (ULONG)nameW.Buffer;
507 if ((status = LdrFindResourceDirectory_U( hmod, &info, 2, &resdir )) != STATUS_SUCCESS)
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 );
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) );
524 /**********************************************************************
525 * EnumResourceLanguagesW (KERNEL32.@)
527 BOOL WINAPI EnumResourceLanguagesW( HMODULE hmod, LPCWSTR type, LPCWSTR name,
528 ENUMRESLANGPROCW lpfun, LONG_PTR lparam )
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)
544 if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS)
546 if ((status = get_res_nameW( name, &nameW )) != STATUS_SUCCESS)
548 info.Type = (ULONG)typeW.Buffer;
549 info.Name = (ULONG)nameW.Buffer;
550 if ((status = LdrFindResourceDirectory_U( hmod, &info, 2, &resdir )) != STATUS_SUCCESS)
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 );
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) );
567 /**********************************************************************
568 * LoadResource (KERNEL32.@)
570 HGLOBAL WINAPI LoadResource( HINSTANCE hModule, HRSRC hRsrc )
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) );
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;
630 struct list resources_list;
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)
661 HRSRC hResource = FindResourceExW(hModule, lpType, lpName, wLang);
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 )
689 HANDLE hModule = NULL;
690 HANDLE hUpdate = NULL;
691 QUEUEDUPDATES *current_updates = NULL;
694 TRACE("%s, %d\n",debugstr_w(pFileName),bDeleteExistingResources);
696 hFile = FindFirstFileW(pFileName, &fd);
697 if(hFile == INVALID_HANDLE_VALUE)
700 SetLastError(ERROR_FILE_NOT_FOUND);
703 if(fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
705 SetLastError(ERROR_FILE_READ_ONLY);
709 hModule = LoadLibraryW(pFileName);
712 SetLastError(ERROR_INVALID_PARAMETER);
716 if(!(hUpdate = GlobalAlloc(GHND, sizeof(QUEUEDUPDATES))))
718 SetLastError(ERROR_OUTOFMEMORY);
721 if(!(current_updates = GlobalLock(hUpdate)))
723 SetLastError(ERROR_INVALID_HANDLE);
726 if(!(current_updates->pFileName = HeapAlloc(GetProcessHeap(), 0, (strlenW(pFileName)+1)*sizeof(WCHAR))))
728 SetLastError(ERROR_OUTOFMEMORY);
731 strcpyW(current_updates->pFileName, pFileName);
732 list_init(¤t_updates->resources_list);
734 if(bDeleteExistingResources)
736 if(!EnumResourceTypesW(hModule, enum_resources_types_delete_all, (LONG_PTR)hUpdate))
741 if(!EnumResourceTypesW(hModule, enum_resources_types_add_all, (LONG_PTR)hUpdate))
747 if(!ret && current_updates)
749 HeapFree(GetProcessHeap(), 0, current_updates->pFileName);
750 GlobalUnlock(hUpdate);
754 if(hUpdate) GlobalUnlock(hUpdate);
755 if(hModule) FreeLibrary(hModule);
756 if(hFile) FindClose(hFile);
761 /***********************************************************************
762 * BeginUpdateResourceA (KERNEL32.@)
764 HANDLE WINAPI BeginUpdateResourceA( LPCSTR pFileName, BOOL bDeleteExistingResources )
766 UNICODE_STRING FileNameW;
768 RtlCreateUnicodeStringFromAsciiz(&FileNameW, pFileName);
769 ret = BeginUpdateResourceW(FileNameW.Buffer, bDeleteExistingResources);
770 RtlFreeUnicodeString(&FileNameW);
775 /***********************************************************************
776 * EndUpdateResourceW (KERNEL32.@)
778 BOOL WINAPI EndUpdateResourceW( HANDLE hUpdate, BOOL fDiscard )
780 QUEUEDUPDATES *current_updates = NULL;
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);
799 /* FIXME: This is the only missing part, an actual implementation */
800 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
807 while ((ptr = list_head(¤t_updates->resources_list)) != NULL)
809 current_resource = LIST_ENTRY(ptr, QUEUEDRESOURCE, entry);
810 list_remove(¤t_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);
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;
841 QUEUEDRESOURCE *current_resource = NULL;
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);
853 if(!(current_resource = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUEDRESOURCE))))
855 SetLastError(ERROR_OUTOFMEMORY);
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);
864 SetLastError(ERROR_OUTOFMEMORY);
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);
873 SetLastError(ERROR_OUTOFMEMORY);
876 if(!(current_resource->lpData = HeapAlloc(GetProcessHeap(), 0, cbData)))
878 SetLastError(ERROR_OUTOFMEMORY);
881 current_resource->wLanguage = wLanguage;
882 memcpy(current_resource->lpData, lpData, cbData);
883 current_resource->cbData = cbData;
884 list_add_tail(¤t_updates->resources_list, ¤t_resource->entry);
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);
900 /***********************************************************************
901 * UpdateResourceA (KERNEL32.@)
903 BOOL WINAPI UpdateResourceA( HANDLE hUpdate, LPCSTR lpType, LPCSTR lpName,
904 WORD wLanguage, LPVOID lpData, DWORD cbData)
907 UNICODE_STRING TypeW;
908 UNICODE_STRING NameW;
910 TypeW.Buffer = (LPWSTR)lpType;
912 RtlCreateUnicodeStringFromAsciiz(&TypeW, lpType);
914 NameW.Buffer = (LPWSTR)lpName;
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);