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"
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
31 #include "wine/winbase16.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(resource
);
36 /* handle conversions */
37 #define HRSRC_32(h16) ((HRSRC)(ULONG_PTR)(h16))
38 #define HRSRC_16(h32) (LOWORD(h32))
39 #define HGLOBAL_32(h16) ((HGLOBAL)(ULONG_PTR)(h16))
40 #define HGLOBAL_16(h32) (LOWORD(h32))
41 #define HMODULE_16(h32) (LOWORD(h32))
44 /* retrieve the resource name to pass to the ntdll functions */
45 static NTSTATUS
get_res_nameA( LPCSTR name
, UNICODE_STRING
*str
)
49 str
->Buffer
= (LPWSTR
)name
;
50 return STATUS_SUCCESS
;
55 if (RtlCharToInteger( name
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
56 return STATUS_INVALID_PARAMETER
;
57 str
->Buffer
= (LPWSTR
)value
;
58 return STATUS_SUCCESS
;
60 RtlCreateUnicodeStringFromAsciiz( str
, name
);
61 RtlUpcaseUnicodeString( str
, str
, FALSE
);
62 return STATUS_SUCCESS
;
65 /* retrieve the resource name to pass to the ntdll functions */
66 static NTSTATUS
get_res_nameW( LPCWSTR name
, UNICODE_STRING
*str
)
70 str
->Buffer
= (LPWSTR
)name
;
71 return STATUS_SUCCESS
;
76 RtlInitUnicodeString( str
, name
);
77 if (RtlUnicodeStringToInteger( str
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
78 return STATUS_INVALID_PARAMETER
;
79 str
->Buffer
= (LPWSTR
)value
;
80 return STATUS_SUCCESS
;
82 RtlCreateUnicodeString( str
, name
);
83 RtlUpcaseUnicodeString( str
, str
, FALSE
);
84 return STATUS_SUCCESS
;
87 /**********************************************************************
88 * FindResourceExA (KERNEL32.@)
90 HRSRC WINAPI
FindResourceExA( HMODULE hModule
, LPCSTR type
, LPCSTR name
, WORD lang
)
93 UNICODE_STRING nameW
, typeW
;
94 LDR_RESOURCE_INFO info
;
95 const IMAGE_RESOURCE_DATA_ENTRY
*entry
= NULL
;
97 TRACE( "%p %s %s %04x\n", hModule
, debugstr_a(type
), debugstr_a(name
), lang
);
99 if (!hModule
) hModule
= GetModuleHandleW(0);
100 else if (!HIWORD(hModule
))
102 return HRSRC_32( FindResource16( HMODULE_16(hModule
), name
, type
) );
105 nameW
.Buffer
= typeW
.Buffer
= NULL
;
106 if ((status
= get_res_nameA( name
, &nameW
)) != STATUS_SUCCESS
) goto done
;
107 if ((status
= get_res_nameA( type
, &typeW
)) != STATUS_SUCCESS
) goto done
;
108 info
.Type
= (ULONG
)typeW
.Buffer
;
109 info
.Name
= (ULONG
)nameW
.Buffer
;
110 info
.Language
= lang
;
111 status
= LdrFindResource_U( hModule
, &info
, 3, &entry
);
113 if (HIWORD(nameW
.Buffer
)) HeapFree( GetProcessHeap(), 0, nameW
.Buffer
);
114 if (HIWORD(typeW
.Buffer
)) HeapFree( GetProcessHeap(), 0, typeW
.Buffer
);
115 if (status
!= STATUS_SUCCESS
) SetLastError( RtlNtStatusToDosError(status
) );
120 /**********************************************************************
121 * FindResourceA (KERNEL32.@)
123 HRSRC WINAPI
FindResourceA( HMODULE hModule
, LPCSTR name
, LPCSTR type
)
125 return FindResourceExA( hModule
, type
, name
, MAKELANGID( LANG_NEUTRAL
, SUBLANG_NEUTRAL
) );
129 /**********************************************************************
130 * FindResourceExW (KERNEL32.@)
132 HRSRC WINAPI
FindResourceExW( HMODULE hModule
, LPCWSTR type
, LPCWSTR name
, WORD lang
)
135 UNICODE_STRING nameW
, typeW
;
136 LDR_RESOURCE_INFO info
;
137 const IMAGE_RESOURCE_DATA_ENTRY
*entry
= NULL
;
139 TRACE( "%p %s %s %04x\n", hModule
, debugstr_w(type
), debugstr_w(name
), lang
);
141 if (!hModule
) hModule
= GetModuleHandleW(0);
142 else if (!HIWORD(hModule
))
149 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, name
, -1, NULL
, 0, NULL
, NULL
);
150 nameA
= HeapAlloc( GetProcessHeap(), 0, len
);
151 if (nameA
) WideCharToMultiByte( CP_ACP
, 0, name
, -1, nameA
, len
, NULL
, NULL
);
153 else nameA
= (LPSTR
)name
;
157 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, type
, -1, NULL
, 0, NULL
, NULL
);
158 typeA
= HeapAlloc( GetProcessHeap(), 0, len
);
159 if (typeA
) WideCharToMultiByte( CP_ACP
, 0, type
, -1, typeA
, len
, NULL
, NULL
);
161 else typeA
= (LPSTR
)type
;
163 ret
= FindResource16( HMODULE_16(hModule
), nameA
, typeA
);
164 if (HIWORD(nameA
)) HeapFree( GetProcessHeap(), 0, nameA
);
165 if (HIWORD(typeA
)) HeapFree( GetProcessHeap(), 0, typeA
);
166 return HRSRC_32(ret
);
169 nameW
.Buffer
= typeW
.Buffer
= NULL
;
170 if ((status
= get_res_nameW( name
, &nameW
)) != STATUS_SUCCESS
) goto done
;
171 if ((status
= get_res_nameW( type
, &typeW
)) != STATUS_SUCCESS
) goto done
;
172 info
.Type
= (ULONG
)typeW
.Buffer
;
173 info
.Name
= (ULONG
)nameW
.Buffer
;
174 info
.Language
= lang
;
175 status
= LdrFindResource_U( hModule
, &info
, 3, &entry
);
177 if (HIWORD(nameW
.Buffer
)) HeapFree( GetProcessHeap(), 0, nameW
.Buffer
);
178 if (HIWORD(typeW
.Buffer
)) HeapFree( GetProcessHeap(), 0, typeW
.Buffer
);
179 if (status
!= STATUS_SUCCESS
) SetLastError( RtlNtStatusToDosError(status
) );
184 /**********************************************************************
185 * FindResourceW (KERNEL32.@)
187 HRSRC WINAPI
FindResourceW( HINSTANCE hModule
, LPCWSTR name
, LPCWSTR type
)
189 return FindResourceExW( hModule
, type
, name
, MAKELANGID( LANG_NEUTRAL
, SUBLANG_NEUTRAL
) );
193 /**********************************************************************
194 * EnumResourceTypesA (KERNEL32.@)
196 BOOL WINAPI
EnumResourceTypesA( HMODULE hmod
, ENUMRESTYPEPROCA lpfun
, LONG_PTR lparam
)
201 DWORD len
= 0, newlen
;
203 const IMAGE_RESOURCE_DIRECTORY
*resdir
;
204 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*et
;
205 const IMAGE_RESOURCE_DIR_STRING_U
*str
;
207 TRACE( "%p %p %lx\n", hmod
, lpfun
, lparam
);
209 if (!hmod
) hmod
= GetModuleHandleA( NULL
);
211 if ((status
= LdrFindResourceDirectory_U( hmod
, NULL
, 0, &resdir
)) != STATUS_SUCCESS
)
213 SetLastError( RtlNtStatusToDosError(status
) );
216 et
= (PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(resdir
+ 1);
217 for (i
= 0; i
< resdir
->NumberOfNamedEntries
+resdir
->NumberOfIdEntries
; i
++)
219 if (et
[i
].u1
.s1
.NameIsString
)
221 str
= (PIMAGE_RESOURCE_DIR_STRING_U
) ((LPBYTE
) resdir
+ et
[i
].u1
.s1
.NameOffset
);
222 newlen
= WideCharToMultiByte( CP_ACP
, 0, str
->NameString
, str
->Length
, NULL
, 0, NULL
, NULL
);
223 if (newlen
+ 1 > len
)
226 if (type
) HeapFree( GetProcessHeap(), 0, type
);
227 if (!(type
= HeapAlloc( GetProcessHeap(), 0, len
))) return FALSE
;
229 WideCharToMultiByte( CP_ACP
, 0, str
->NameString
, str
->Length
, type
, len
, NULL
, NULL
);
231 ret
= lpfun(hmod
,type
,lparam
);
235 ret
= lpfun( hmod
, (LPSTR
)(int)et
[i
].u1
.s2
.Id
, lparam
);
239 if (type
) HeapFree( GetProcessHeap(), 0, type
);
244 /**********************************************************************
245 * EnumResourceTypesW (KERNEL32.@)
247 BOOL WINAPI
EnumResourceTypesW( HMODULE hmod
, ENUMRESTYPEPROCW lpfun
, LONG_PTR lparam
)
254 const IMAGE_RESOURCE_DIRECTORY
*resdir
;
255 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*et
;
256 const IMAGE_RESOURCE_DIR_STRING_U
*str
;
258 TRACE( "%p %p %lx\n", hmod
, lpfun
, lparam
);
260 if (!hmod
) hmod
= GetModuleHandleW( NULL
);
262 if ((status
= LdrFindResourceDirectory_U( hmod
, NULL
, 0, &resdir
)) != STATUS_SUCCESS
)
264 SetLastError( RtlNtStatusToDosError(status
) );
267 et
= (PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(resdir
+ 1);
268 for (i
= 0; i
< resdir
->NumberOfNamedEntries
+ resdir
->NumberOfIdEntries
; i
++)
270 if (et
[i
].u1
.s1
.NameIsString
)
272 str
= (PIMAGE_RESOURCE_DIR_STRING_U
) ((LPBYTE
) resdir
+ et
[i
].u1
.s1
.NameOffset
);
273 if (str
->Length
+ 1 > len
)
275 len
= str
->Length
+ 1;
276 if (type
) HeapFree( GetProcessHeap(), 0, type
);
277 if (!(type
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return FALSE
;
279 memcpy(type
, str
->NameString
, str
->Length
* sizeof (WCHAR
));
280 type
[str
->Length
] = 0;
281 ret
= lpfun(hmod
,type
,lparam
);
285 ret
= lpfun( hmod
, (LPWSTR
)(int)et
[i
].u1
.s2
.Id
, lparam
);
289 if (type
) HeapFree( GetProcessHeap(), 0, type
);
294 /**********************************************************************
295 * EnumResourceNamesA (KERNEL32.@)
297 BOOL WINAPI
EnumResourceNamesA( HMODULE hmod
, LPCSTR type
, ENUMRESNAMEPROCA lpfun
, LONG_PTR lparam
)
301 DWORD len
= 0, newlen
;
304 UNICODE_STRING typeW
;
305 LDR_RESOURCE_INFO info
;
306 const IMAGE_RESOURCE_DIRECTORY
*basedir
, *resdir
;
307 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*et
;
308 const IMAGE_RESOURCE_DIR_STRING_U
*str
;
310 TRACE( "%p %s %p %lx\n", hmod
, debugstr_a(type
), lpfun
, lparam
);
312 if (!hmod
) hmod
= GetModuleHandleA( NULL
);
314 if ((status
= LdrFindResourceDirectory_U( hmod
, NULL
, 0, &basedir
)) != STATUS_SUCCESS
)
316 if ((status
= get_res_nameA( type
, &typeW
)) != STATUS_SUCCESS
)
318 info
.Type
= (ULONG
)typeW
.Buffer
;
319 if ((status
= LdrFindResourceDirectory_U( hmod
, &info
, 1, &resdir
)) != STATUS_SUCCESS
)
322 et
= (IMAGE_RESOURCE_DIRECTORY_ENTRY
*)(resdir
+ 1);
323 for (i
= 0; i
< resdir
->NumberOfNamedEntries
+resdir
->NumberOfIdEntries
; i
++)
325 if (et
[i
].u1
.s1
.NameIsString
)
327 str
= (IMAGE_RESOURCE_DIR_STRING_U
*) ((LPBYTE
) basedir
+ et
[i
].u1
.s1
.NameOffset
);
328 newlen
= WideCharToMultiByte(CP_ACP
, 0, str
->NameString
, str
->Length
, NULL
, 0, NULL
, NULL
);
329 if (newlen
+ 1 > len
)
332 if (name
) HeapFree( GetProcessHeap(), 0, name
);
333 if (!(name
= HeapAlloc(GetProcessHeap(), 0, len
+ 1 )))
339 WideCharToMultiByte( CP_ACP
, 0, str
->NameString
, str
->Length
, name
, len
, NULL
, NULL
);
341 ret
= lpfun(hmod
,type
,name
,lparam
);
345 ret
= lpfun( hmod
, type
, (LPSTR
)(int)et
[i
].u1
.s2
.Id
, lparam
);
350 if (name
) HeapFree( GetProcessHeap(), 0, name
);
351 if (HIWORD(typeW
.Buffer
)) HeapFree( GetProcessHeap(), 0, typeW
.Buffer
);
352 if (status
!= STATUS_SUCCESS
) SetLastError( RtlNtStatusToDosError(status
) );
357 /**********************************************************************
358 * EnumResourceNamesW (KERNEL32.@)
360 BOOL WINAPI
EnumResourceNamesW( HMODULE hmod
, LPCWSTR type
, ENUMRESNAMEPROCW lpfun
, LONG_PTR lparam
)
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_w(type
), lpfun
, lparam
);
375 if (!hmod
) hmod
= GetModuleHandleW( NULL
);
377 if ((status
= LdrFindResourceDirectory_U( hmod
, NULL
, 0, &basedir
)) != STATUS_SUCCESS
)
379 if ((status
= get_res_nameW( type
, &typeW
)) != STATUS_SUCCESS
)
381 info
.Type
= (ULONG
)typeW
.Buffer
;
382 if ((status
= LdrFindResourceDirectory_U( hmod
, &info
, 1, &resdir
)) != STATUS_SUCCESS
)
385 et
= (PIMAGE_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 if (str
->Length
+ 1 > len
)
393 len
= str
->Length
+ 1;
394 if (name
) HeapFree( GetProcessHeap(), 0, name
);
395 if (!(name
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
401 memcpy(name
, str
->NameString
, str
->Length
* sizeof (WCHAR
));
402 name
[str
->Length
] = 0;
403 ret
= lpfun(hmod
,type
,name
,lparam
);
407 ret
= lpfun( hmod
, type
, (LPWSTR
)(int)et
[i
].u1
.s2
.Id
, lparam
);
412 if (name
) HeapFree( GetProcessHeap(), 0, name
);
413 if (HIWORD(typeW
.Buffer
)) HeapFree( GetProcessHeap(), 0, typeW
.Buffer
);
414 if (status
!= STATUS_SUCCESS
) SetLastError( RtlNtStatusToDosError(status
) );
419 /**********************************************************************
420 * EnumResourceLanguagesA (KERNEL32.@)
422 BOOL WINAPI
EnumResourceLanguagesA( HMODULE hmod
, LPCSTR type
, LPCSTR name
,
423 ENUMRESLANGPROCA lpfun
, LONG_PTR lparam
)
428 UNICODE_STRING typeW
, nameW
;
429 LDR_RESOURCE_INFO info
;
430 const IMAGE_RESOURCE_DIRECTORY
*basedir
, *resdir
;
431 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*et
;
433 TRACE( "%p %s %s %p %lx\n", hmod
, debugstr_a(type
), debugstr_a(name
), lpfun
, lparam
);
435 if (!hmod
) hmod
= GetModuleHandleA( NULL
);
436 typeW
.Buffer
= nameW
.Buffer
= NULL
;
437 if ((status
= LdrFindResourceDirectory_U( hmod
, NULL
, 0, &basedir
)) != STATUS_SUCCESS
)
439 if ((status
= get_res_nameA( type
, &typeW
)) != STATUS_SUCCESS
)
441 if ((status
= get_res_nameA( name
, &nameW
)) != STATUS_SUCCESS
)
443 info
.Type
= (ULONG
)typeW
.Buffer
;
444 info
.Name
= (ULONG
)nameW
.Buffer
;
445 if ((status
= LdrFindResourceDirectory_U( hmod
, &info
, 2, &resdir
)) != STATUS_SUCCESS
)
448 et
= (PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(resdir
+ 1);
449 for (i
= 0; i
< resdir
->NumberOfNamedEntries
+ resdir
->NumberOfIdEntries
; i
++)
451 ret
= lpfun( hmod
, type
, name
, et
[i
].u1
.s2
.Id
, lparam
);
455 if (HIWORD(typeW
.Buffer
)) HeapFree( GetProcessHeap(), 0, typeW
.Buffer
);
456 if (HIWORD(nameW
.Buffer
)) HeapFree( GetProcessHeap(), 0, nameW
.Buffer
);
457 if (status
!= STATUS_SUCCESS
) SetLastError( RtlNtStatusToDosError(status
) );
462 /**********************************************************************
463 * EnumResourceLanguagesW (KERNEL32.@)
465 BOOL WINAPI
EnumResourceLanguagesW( HMODULE hmod
, LPCWSTR type
, LPCWSTR name
,
466 ENUMRESLANGPROCW lpfun
, LONG_PTR lparam
)
471 UNICODE_STRING typeW
, nameW
;
472 LDR_RESOURCE_INFO info
;
473 const IMAGE_RESOURCE_DIRECTORY
*basedir
, *resdir
;
474 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*et
;
476 TRACE( "%p %s %s %p %lx\n", hmod
, debugstr_w(type
), debugstr_w(name
), lpfun
, lparam
);
478 if (!hmod
) hmod
= GetModuleHandleW( NULL
);
479 typeW
.Buffer
= nameW
.Buffer
= NULL
;
480 if ((status
= LdrFindResourceDirectory_U( hmod
, NULL
, 0, &basedir
)) != STATUS_SUCCESS
)
482 if ((status
= get_res_nameW( type
, &typeW
)) != STATUS_SUCCESS
)
484 if ((status
= get_res_nameW( name
, &nameW
)) != STATUS_SUCCESS
)
486 info
.Type
= (ULONG
)typeW
.Buffer
;
487 info
.Name
= (ULONG
)nameW
.Buffer
;
488 if ((status
= LdrFindResourceDirectory_U( hmod
, &info
, 2, &resdir
)) != STATUS_SUCCESS
)
491 et
= (PIMAGE_RESOURCE_DIRECTORY_ENTRY
)(resdir
+ 1);
492 for (i
= 0; i
< resdir
->NumberOfNamedEntries
+ resdir
->NumberOfIdEntries
; i
++)
494 ret
= lpfun( hmod
, type
, name
, et
[i
].u1
.s2
.Id
, lparam
);
498 if (HIWORD(typeW
.Buffer
)) HeapFree( GetProcessHeap(), 0, typeW
.Buffer
);
499 if (HIWORD(nameW
.Buffer
)) HeapFree( GetProcessHeap(), 0, nameW
.Buffer
);
500 if (status
!= STATUS_SUCCESS
) SetLastError( RtlNtStatusToDosError(status
) );
505 /**********************************************************************
506 * LoadResource (KERNEL32.@)
508 HGLOBAL WINAPI
LoadResource( HINSTANCE hModule
, HRSRC hRsrc
)
513 TRACE( "%p %p\n", hModule
, hRsrc
);
515 if (hModule
&& !HIWORD(hModule
))
516 /* FIXME: should convert return to 32-bit resource */
517 return HGLOBAL_32( LoadResource16( HMODULE_16(hModule
), HRSRC_16(hRsrc
) ) );
519 if (!hRsrc
) return 0;
520 if (!hModule
) hModule
= GetModuleHandleA( NULL
);
521 status
= LdrAccessResource( hModule
, (IMAGE_RESOURCE_DATA_ENTRY
*)hRsrc
, &ret
, NULL
);
522 if (status
!= STATUS_SUCCESS
) SetLastError( RtlNtStatusToDosError(status
) );
527 /**********************************************************************
528 * LockResource (KERNEL32.@)
530 LPVOID WINAPI
LockResource( HGLOBAL handle
)
532 TRACE("(%p)\n", handle
);
534 if (HIWORD( handle
)) /* 32-bit memory handle */
535 return (LPVOID
)handle
;
537 /* 16-bit memory handle */
538 return LockResource16( HGLOBAL_16(handle
) );
542 /**********************************************************************
543 * FreeResource (KERNEL32.@)
545 BOOL WINAPI
FreeResource( HGLOBAL handle
)
547 if (HIWORD(handle
)) return 0; /* 32-bit memory handle: nothing to do */
548 return FreeResource16( HGLOBAL_16(handle
) );
552 /**********************************************************************
553 * SizeofResource (KERNEL32.@)
555 DWORD WINAPI
SizeofResource( HINSTANCE hModule
, HRSRC hRsrc
)
557 if (hModule
&& !HIWORD(hModule
))
558 return SizeofResource16( HMODULE_16(hModule
), HRSRC_16(hRsrc
) );
560 if (!hRsrc
) return 0;
561 return ((PIMAGE_RESOURCE_DATA_ENTRY
)hRsrc
)->Size
;