4 * Copyright 1995 Thomas Sandford
5 * Copyright 1996 Martin von Loewis
6 * Copyright 2003 Alexandre Julliard
7 * Copyright 1993 Robert J. Amstadt
8 * Copyright 1997 Marcus Meissner
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 /* INCLUDES *****************************************************************/
32 NTSTATUS
find_entry( PVOID BaseAddress
, LDR_RESOURCE_INFO
*info
,
33 ULONG level
, void **ret
, int want_dir
);
35 /* FUNCTIONS ****************************************************************/
37 _SEH_FILTER(page_fault
)
39 if (_SEH_GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
||
40 _SEH_GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION
)
41 return EXCEPTION_EXECUTE_HANDLER
;
42 return EXCEPTION_CONTINUE_SEARCH
;
45 /**********************************************************************
48 * Check if a module handle is for a LOAD_LIBRARY_AS_DATAFILE module.
50 static int is_data_file_module( PVOID BaseAddress
)
52 return (ULONG_PTR
)BaseAddress
& 1;
56 /**********************************************************************
59 * push a language in the list of languages to try
61 int push_language( USHORT
*list
, ULONG pos
, WORD lang
)
64 for (i
= 0; i
< pos
; i
++) if (list
[i
] == lang
) return pos
;
70 /**********************************************************************
73 * Find the first suitable entry in a resource directory
75 IMAGE_RESOURCE_DIRECTORY
*find_first_entry( IMAGE_RESOURCE_DIRECTORY
*dir
,
76 void *root
, int want_dir
)
78 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*entry
= (const IMAGE_RESOURCE_DIRECTORY_ENTRY
*)(dir
+ 1);
81 for (pos
= 0; pos
< dir
->NumberOfNamedEntries
+ dir
->NumberOfIdEntries
; pos
++)
83 if (!entry
[pos
].DataIsDirectory
== !want_dir
)
84 return (IMAGE_RESOURCE_DIRECTORY
*)((char *)root
+ entry
[pos
].OffsetToDirectory
);
90 /**********************************************************************
93 * Find an entry by id in a resource directory
95 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_id( IMAGE_RESOURCE_DIRECTORY
*dir
,
96 WORD id
, void *root
, int want_dir
)
98 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*entry
;
101 entry
= (const IMAGE_RESOURCE_DIRECTORY_ENTRY
*)(dir
+ 1);
102 min
= dir
->NumberOfNamedEntries
;
103 max
= min
+ dir
->NumberOfIdEntries
- 1;
106 pos
= (min
+ max
) / 2;
107 if (entry
[pos
].Id
== id
)
109 if (!entry
[pos
].DataIsDirectory
== !want_dir
)
111 DPRINT("root %p dir %p id %04x ret %p\n",
112 root
, dir
, id
, (const char*)root
+ entry
[pos
].OffsetToDirectory
);
113 return (IMAGE_RESOURCE_DIRECTORY
*)((char *)root
+ entry
[pos
].OffsetToDirectory
);
117 if (entry
[pos
].Id
> id
) max
= pos
- 1;
120 DPRINT("root %p dir %p id %04x not found\n", root
, dir
, id
);
125 /**********************************************************************
128 * Find an entry by name in a resource directory
130 IMAGE_RESOURCE_DIRECTORY
*find_entry_by_name( IMAGE_RESOURCE_DIRECTORY
*dir
,
131 LPCWSTR name
, void *root
,
134 const IMAGE_RESOURCE_DIRECTORY_ENTRY
*entry
;
135 const IMAGE_RESOURCE_DIR_STRING_U
*str
;
136 int min
, max
, res
, pos
, namelen
;
138 if (!((ULONG_PTR
)name
& 0xFFFF0000)) return find_entry_by_id( dir
, (ULONG_PTR
)name
& 0xFFFF, root
, want_dir
);
139 entry
= (const IMAGE_RESOURCE_DIRECTORY_ENTRY
*)(dir
+ 1);
140 namelen
= wcslen(name
);
142 max
= dir
->NumberOfNamedEntries
- 1;
145 pos
= (min
+ max
) / 2;
146 str
= (const IMAGE_RESOURCE_DIR_STRING_U
*)((const char *)root
+ entry
[pos
].NameOffset
);
147 res
= _wcsnicmp( name
, str
->NameString
, str
->Length
);
148 if (!res
&& namelen
== str
->Length
)
150 if (!entry
[pos
].DataIsDirectory
== !want_dir
)
152 DPRINT("root %p dir %p name %ws ret %p\n",
153 root
, dir
, name
, (const char*)root
+ entry
[pos
].OffsetToDirectory
);
154 return (IMAGE_RESOURCE_DIRECTORY
*)((char *)root
+ entry
[pos
].OffsetToDirectory
);
158 if (res
< 0) max
= pos
- 1;
161 DPRINT("root %p dir %p name %ws not found\n", root
, dir
, name
);
166 NTSTATUS NTAPI
LdrpAccessResource( PVOID BaseAddress
, IMAGE_RESOURCE_DATA_ENTRY
*entry
,
167 void **ptr
, ULONG
*size
)
169 static NTSTATUS
LdrpAccessResource( PVOID BaseAddress
, IMAGE_RESOURCE_DATA_ENTRY
*entry
,
170 void **ptr
, ULONG
*size
)
173 NTSTATUS status
= STATUS_SUCCESS
;
179 if (!RtlImageDirectoryEntryToData( BaseAddress
, TRUE
, IMAGE_DIRECTORY_ENTRY_RESOURCE
, &dirsize
))
180 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
185 if (is_data_file_module(BaseAddress
))
187 PVOID mod
= (PVOID
)((ULONG_PTR
)BaseAddress
& ~1);
188 *ptr
= RtlImageRvaToVa( RtlImageNtHeader(mod
), mod
, entry
->OffsetToData
, NULL
);
190 else *ptr
= (char *)BaseAddress
+ entry
->OffsetToData
;
192 if (size
) *size
= entry
->Size
;
195 _SEH_EXCEPT(page_fault
)
197 status
= _SEH_GetExceptionCode();
208 LdrFindResource_U(PVOID BaseAddress
,
209 PLDR_RESOURCE_INFO ResourceInfo
,
211 PIMAGE_RESOURCE_DATA_ENTRY
* ResourceDataEntry
)
214 NTSTATUS status
= STATUS_SUCCESS
;
220 DPRINT( "module %p type %ws name %ws lang %04lx level %ld\n",
221 BaseAddress
, (LPCWSTR
)ResourceInfo
->Type
,
222 Level
> 1 ? (LPCWSTR
)ResourceInfo
->Name
: L
"",
223 Level
> 2 ? ResourceInfo
->Language
: 0, Level
);
226 status
= find_entry( BaseAddress
, ResourceInfo
, Level
, &res
, FALSE
);
227 if (status
== STATUS_SUCCESS
) *ResourceDataEntry
= res
;
229 _SEH_EXCEPT(page_fault
)
231 status
= _SEH_GetExceptionCode();
242 LdrAccessResource(IN PVOID BaseAddress
,
243 IN PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry
,
244 OUT PVOID
* Resource OPTIONAL
,
245 OUT PULONG Size OPTIONAL
)
247 return LdrpAccessResource( BaseAddress
, ResourceDataEntry
, Resource
, Size
);
255 LdrFindResourceDirectory_U(IN PVOID BaseAddress
,
256 IN PLDR_RESOURCE_INFO info
,
258 OUT PIMAGE_RESOURCE_DIRECTORY
* addr
)
261 NTSTATUS status
= STATUS_SUCCESS
;
267 DPRINT( "module %p type %ws name %ws lang %04lx level %ld\n",
268 BaseAddress
, (LPCWSTR
)info
->Type
,
269 level
> 1 ? (LPCWSTR
)info
->Name
: L
"",
270 level
> 2 ? info
->Language
: 0, level
);
273 status
= find_entry( BaseAddress
, info
, level
, &res
, TRUE
);
274 if (status
== STATUS_SUCCESS
) *addr
= res
;
276 _SEH_EXCEPT(page_fault
)
278 status
= _SEH_GetExceptionCode();
289 LdrEnumResources(IN PVOID BaseAddress
,
290 IN PLDR_RESOURCE_INFO ResourceInfo
,
292 IN OUT PULONG ResourceCount
,
293 OUT PVOID Resources OPTIONAL
)
296 return STATUS_NOT_IMPLEMENTED
;