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
35 #include "wine/winbase16.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(resource);
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))
48 /* retrieve the resource name to pass to the ntdll functions */
49 static NTSTATUS get_res_nameA( LPCSTR name, UNICODE_STRING *str )
53 str->Buffer = (LPWSTR)name;
54 return STATUS_SUCCESS;
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;
64 RtlCreateUnicodeStringFromAsciiz( str, name );
65 RtlUpcaseUnicodeString( str, str, FALSE );
66 return STATUS_SUCCESS;
69 /* retrieve the resource name to pass to the ntdll functions */
70 static NTSTATUS get_res_nameW( LPCWSTR name, UNICODE_STRING *str )
74 str->Buffer = (LPWSTR)name;
75 return STATUS_SUCCESS;
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;
86 RtlCreateUnicodeString( str, name );
87 RtlUpcaseUnicodeString( str, str, FALSE );
88 return STATUS_SUCCESS;
91 /**********************************************************************
92 * FindResourceExA (KERNEL32.@)
94 HRSRC WINAPI FindResourceExA( HMODULE hModule, LPCSTR type, LPCSTR name, WORD lang )
97 UNICODE_STRING nameW, typeW;
98 LDR_RESOURCE_INFO info;
99 const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL;
101 TRACE( "%p %s %s %04x\n", hModule, debugstr_a(type), debugstr_a(name), lang );
103 if (!hModule) hModule = GetModuleHandleW(0);
104 else if (!HIWORD(hModule))
106 return HRSRC_32( FindResource16( HMODULE_16(hModule), name, type ) );
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 );
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) );
124 /**********************************************************************
125 * FindResourceA (KERNEL32.@)
127 HRSRC WINAPI FindResourceA( HMODULE hModule, LPCSTR name, LPCSTR type )
129 return FindResourceExA( hModule, type, name, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
133 /**********************************************************************
134 * FindResourceExW (KERNEL32.@)
136 HRSRC WINAPI FindResourceExW( HMODULE hModule, LPCWSTR type, LPCWSTR name, WORD lang )
139 UNICODE_STRING nameW, typeW;
140 LDR_RESOURCE_INFO info;
141 const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL;
143 TRACE( "%p %s %s %04x\n", hModule, debugstr_w(type), debugstr_w(name), lang );
145 if (!hModule) hModule = GetModuleHandleW(0);
146 else if (!HIWORD(hModule))
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 );
157 else nameA = (LPSTR)name;
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 );
165 else typeA = (LPSTR)type;
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);
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 );
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) );
188 /**********************************************************************
189 * FindResourceW (KERNEL32.@)
191 HRSRC WINAPI FindResourceW( HINSTANCE hModule, LPCWSTR name, LPCWSTR type )
193 return FindResourceExW( hModule, type, name, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
197 /**********************************************************************
198 * EnumResourceTypesA (KERNEL32.@)
200 BOOL WINAPI EnumResourceTypesA( HMODULE hmod, ENUMRESTYPEPROCA lpfun, LONG_PTR lparam )
205 DWORD len = 0, newlen;
207 const IMAGE_RESOURCE_DIRECTORY *resdir;
208 const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
209 const IMAGE_RESOURCE_DIR_STRING_U *str;
211 TRACE( "%p %p %lx\n", hmod, lpfun, lparam );
213 if (!hmod) hmod = GetModuleHandleA( NULL );
215 if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &resdir )) != STATUS_SUCCESS)
217 SetLastError( RtlNtStatusToDosError(status) );
220 et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
221 for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
223 if (et[i].u1.s1.NameIsString)
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)
230 if (type) HeapFree( GetProcessHeap(), 0, type );
231 if (!(type = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE;
233 WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, type, len, NULL, NULL);
235 ret = lpfun(hmod,type,lparam);
239 ret = lpfun( hmod, (LPSTR)(int)et[i].u1.s2.Id, lparam );
243 if (type) HeapFree( GetProcessHeap(), 0, type );
248 /**********************************************************************
249 * EnumResourceTypesW (KERNEL32.@)
251 BOOL WINAPI EnumResourceTypesW( HMODULE hmod, ENUMRESTYPEPROCW lpfun, LONG_PTR lparam )
258 const IMAGE_RESOURCE_DIRECTORY *resdir;
259 const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
260 const IMAGE_RESOURCE_DIR_STRING_U *str;
262 TRACE( "%p %p %lx\n", hmod, lpfun, lparam );
264 if (!hmod) hmod = GetModuleHandleW( NULL );
266 if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &resdir )) != STATUS_SUCCESS)
268 SetLastError( RtlNtStatusToDosError(status) );
271 et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
272 for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++)
274 if (et[i].u1.s1.NameIsString)
276 str = (PIMAGE_RESOURCE_DIR_STRING_U) ((LPBYTE) resdir + et[i].u1.s1.NameOffset);
277 if (str->Length + 1 > len)
279 len = str->Length + 1;
280 if (type) HeapFree( GetProcessHeap(), 0, type );
281 if (!(type = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return FALSE;
283 memcpy(type, str->NameString, str->Length * sizeof (WCHAR));
284 type[str->Length] = 0;
285 ret = lpfun(hmod,type,lparam);
289 ret = lpfun( hmod, (LPWSTR)(int)et[i].u1.s2.Id, lparam );
293 if (type) HeapFree( GetProcessHeap(), 0, type );
298 /**********************************************************************
299 * EnumResourceNamesA (KERNEL32.@)
301 BOOL WINAPI EnumResourceNamesA( HMODULE hmod, LPCSTR type, ENUMRESNAMEPROCA lpfun, LONG_PTR lparam )
305 DWORD len = 0, newlen;
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;
314 TRACE( "%p %s %p %lx\n", hmod, debugstr_a(type), lpfun, lparam );
316 if (!hmod) hmod = GetModuleHandleA( NULL );
318 if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
320 if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS)
322 info.Type = (ULONG)typeW.Buffer;
323 if ((status = LdrFindResourceDirectory_U( hmod, &info, 1, &resdir )) != STATUS_SUCCESS)
326 et = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1);
327 for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
329 if (et[i].u1.s1.NameIsString)
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)
336 if (name) HeapFree( GetProcessHeap(), 0, name );
337 if (!(name = HeapAlloc(GetProcessHeap(), 0, len + 1 )))
343 WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, name, len, NULL, NULL );
345 ret = lpfun(hmod,type,name,lparam);
349 ret = lpfun( hmod, type, (LPSTR)(int)et[i].u1.s2.Id, lparam );
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) );
361 /**********************************************************************
362 * EnumResourceNamesW (KERNEL32.@)
364 BOOL WINAPI EnumResourceNamesW( HMODULE hmod, LPCWSTR type, ENUMRESNAMEPROCW lpfun, LONG_PTR lparam )
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;
377 TRACE( "%p %s %p %lx\n", hmod, debugstr_w(type), lpfun, lparam );
379 if (!hmod) hmod = GetModuleHandleW( NULL );
381 if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
383 if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS)
385 info.Type = (ULONG)typeW.Buffer;
386 if ((status = LdrFindResourceDirectory_U( hmod, &info, 1, &resdir )) != STATUS_SUCCESS)
389 et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
390 for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++)
392 if (et[i].u1.s1.NameIsString)
394 str = (IMAGE_RESOURCE_DIR_STRING_U *) ((LPBYTE) basedir + et[i].u1.s1.NameOffset);
395 if (str->Length + 1 > len)
397 len = str->Length + 1;
398 if (name) HeapFree( GetProcessHeap(), 0, name );
399 if (!(name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
405 memcpy(name, str->NameString, str->Length * sizeof (WCHAR));
406 name[str->Length] = 0;
407 ret = lpfun(hmod,type,name,lparam);
411 ret = lpfun( hmod, type, (LPWSTR)(int)et[i].u1.s2.Id, lparam );
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) );
423 /**********************************************************************
424 * EnumResourceLanguagesA (KERNEL32.@)
426 BOOL WINAPI EnumResourceLanguagesA( HMODULE hmod, LPCSTR type, LPCSTR name,
427 ENUMRESLANGPROCA lpfun, LONG_PTR lparam )
432 UNICODE_STRING typeW, nameW;
433 LDR_RESOURCE_INFO info;
434 const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir;
435 const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
437 TRACE( "%p %s %s %p %lx\n", hmod, debugstr_a(type), debugstr_a(name), lpfun, lparam );
439 if (!hmod) hmod = GetModuleHandleA( NULL );
440 typeW.Buffer = nameW.Buffer = NULL;
441 if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
443 if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS)
445 if ((status = get_res_nameA( name, &nameW )) != STATUS_SUCCESS)
447 info.Type = (ULONG)typeW.Buffer;
448 info.Name = (ULONG)nameW.Buffer;
449 if ((status = LdrFindResourceDirectory_U( hmod, &info, 2, &resdir )) != STATUS_SUCCESS)
452 et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
453 for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++)
455 ret = lpfun( hmod, type, name, et[i].u1.s2.Id, lparam );
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) );
466 /**********************************************************************
467 * EnumResourceLanguagesW (KERNEL32.@)
469 BOOL WINAPI EnumResourceLanguagesW( HMODULE hmod, LPCWSTR type, LPCWSTR name,
470 ENUMRESLANGPROCW lpfun, LONG_PTR lparam )
475 UNICODE_STRING typeW, nameW;
476 LDR_RESOURCE_INFO info;
477 const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir;
478 const IMAGE_RESOURCE_DIRECTORY_ENTRY *et;
480 TRACE( "%p %s %s %p %lx\n", hmod, debugstr_w(type), debugstr_w(name), lpfun, lparam );
482 if (!hmod) hmod = GetModuleHandleW( NULL );
483 typeW.Buffer = nameW.Buffer = NULL;
484 if ((status = LdrFindResourceDirectory_U( hmod, NULL, 0, &basedir )) != STATUS_SUCCESS)
486 if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS)
488 if ((status = get_res_nameW( name, &nameW )) != STATUS_SUCCESS)
490 info.Type = (ULONG)typeW.Buffer;
491 info.Name = (ULONG)nameW.Buffer;
492 if ((status = LdrFindResourceDirectory_U( hmod, &info, 2, &resdir )) != STATUS_SUCCESS)
495 et = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resdir + 1);
496 for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++)
498 ret = lpfun( hmod, type, name, et[i].u1.s2.Id, lparam );
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) );
509 /**********************************************************************
510 * LoadResource (KERNEL32.@)
512 HGLOBAL WINAPI LoadResource( HINSTANCE hModule, HRSRC hRsrc )
517 TRACE( "%p %p\n", hModule, hRsrc );
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) ) );
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) );
531 /**********************************************************************
532 * LockResource (KERNEL32.@)
534 LPVOID WINAPI LockResource( HGLOBAL handle )
536 TRACE("(%p)\n", handle );
538 if (HIWORD( handle )) /* 32-bit memory handle */
539 return (LPVOID)handle;
541 /* 16-bit memory handle */
542 return LockResource16( HGLOBAL_16(handle) );
546 /**********************************************************************
547 * FreeResource (KERNEL32.@)
549 BOOL WINAPI FreeResource( HGLOBAL handle )
551 if (HIWORD(handle)) return 0; /* 32-bit memory handle: nothing to do */
552 return FreeResource16( HGLOBAL_16(handle) );
556 /**********************************************************************
557 * SizeofResource (KERNEL32.@)
559 DWORD WINAPI SizeofResource( HINSTANCE hModule, HRSRC hRsrc )
561 if (hModule && !HIWORD(hModule))
562 return SizeofResource16( HMODULE_16(hModule), HRSRC_16(hRsrc) );
564 if (!hRsrc) return 0;
565 return ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->Size;
569 /***********************************************************************
570 * BeginUpdateResourceA (KERNEL32.@)
572 HANDLE WINAPI BeginUpdateResourceA( LPCSTR pFileName, BOOL bDeleteExistingResources )
574 FIXME("(%s,%d): stub\n",debugstr_a(pFileName),bDeleteExistingResources);
575 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
580 /***********************************************************************
581 * BeginUpdateResourceW (KERNEL32.@)
583 HANDLE WINAPI BeginUpdateResourceW( LPCWSTR pFileName, BOOL bDeleteExistingResources )
585 FIXME("(%s,%d): stub\n",debugstr_w(pFileName),bDeleteExistingResources);
586 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
591 /***********************************************************************
592 * EndUpdateResourceA (KERNEL32.@)
594 BOOL WINAPI EndUpdateResourceA( HANDLE hUpdate, BOOL fDiscard )
596 FIXME("(%p,%d): stub\n",hUpdate, fDiscard);
597 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
602 /***********************************************************************
603 * EndUpdateResourceW (KERNEL32.@)
605 BOOL WINAPI EndUpdateResourceW( HANDLE hUpdate, BOOL fDiscard )
607 FIXME("(%p,%d): stub\n",hUpdate, fDiscard);
608 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
613 /***********************************************************************
614 * UpdateResourceA (KERNEL32.@)
616 BOOL WINAPI UpdateResourceA(
625 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
630 /***********************************************************************
631 * UpdateResourceW (KERNEL32.@)
633 BOOL WINAPI UpdateResourceW(
642 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);