Alexandre Julliard : ntdll: Map imported apiset dlls to their target library.
Alexandre Julliard
julliard at winehq.org
Tue Feb 22 16:06:51 CST 2022
Module: wine
Branch: master
Commit: 31e151362bc5e82a988a4f9ff4309697525eda3f
URL: https://source.winehq.org/git/wine.git/?a=commit;h=31e151362bc5e82a988a4f9ff4309697525eda3f
Author: Alexandre Julliard <julliard at winehq.org>
Date: Tue Feb 22 11:43:04 2022 +0100
ntdll: Map imported apiset dlls to their target library.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/loader.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++
dlls/ntdll/unix/loader.c | 1 -
2 files changed, 86 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 2c3e62f6e25..387f8b6b2d6 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -587,16 +587,102 @@ static WINE_MODREF *find_fileid_module( const struct file_id *id )
}
+/******************************************************************************
+ * get_apiset_entry
+ */
+static NTSTATUS get_apiset_entry( const API_SET_NAMESPACE *map, const WCHAR *name, ULONG len,
+ const API_SET_NAMESPACE_ENTRY **entry )
+{
+ const API_SET_HASH_ENTRY *hash_entry;
+ ULONG hash, i, hash_len;
+ int min, max;
+
+ if (len <= 4) return STATUS_INVALID_PARAMETER;
+ if (wcsnicmp( name, L"api-", 4 ) && wcsnicmp( name, L"ext-", 4 )) return STATUS_INVALID_PARAMETER;
+ if (!map) return STATUS_APISET_NOT_PRESENT;
+
+ for (i = hash_len = 0; i < len; i++)
+ {
+ if (name[i] == '.') break;
+ if (name[i] == '-') hash_len = i;
+ }
+ for (i = hash = 0; i < hash_len; i++)
+ hash = hash * map->HashFactor + ((name[i] >= 'A' && name[i] <= 'Z') ? name[i] + 32 : name[i]);
+
+ hash_entry = (API_SET_HASH_ENTRY *)((char *)map + map->HashOffset);
+ min = 0;
+ max = map->Count - 1;
+ while (min <= max)
+ {
+ int pos = (min + max) / 2;
+ if (hash_entry[pos].Hash < hash) min = pos + 1;
+ else if (hash_entry[pos].Hash > hash) max = pos - 1;
+ else
+ {
+ *entry = (API_SET_NAMESPACE_ENTRY *)((char *)map + map->EntryOffset) + hash_entry[pos].Index;
+ if ((*entry)->HashedLength != hash_len * sizeof(WCHAR)) break;
+ if (wcsnicmp( (WCHAR *)((char *)map + (*entry)->NameOffset), name, hash_len )) break;
+ return STATUS_SUCCESS;
+ }
+ }
+ return STATUS_APISET_NOT_PRESENT;
+}
+
+
+/******************************************************************************
+ * get_apiset_target
+ */
+static NTSTATUS get_apiset_target( const API_SET_NAMESPACE *map, const API_SET_NAMESPACE_ENTRY *entry,
+ const WCHAR *host, UNICODE_STRING *ret )
+{
+ const API_SET_VALUE_ENTRY *value = (API_SET_VALUE_ENTRY *)((char *)map + entry->ValueOffset);
+ ULONG i, len;
+
+ if (!entry->ValueCount) return STATUS_DLL_NOT_FOUND;
+ if (host)
+ {
+ /* look for specific host in entries 1..n, entry 0 is the default */
+ for (i = 1; i < entry->ValueCount; i++)
+ {
+ len = value[i].NameLength / sizeof(WCHAR);
+ if (!wcsnicmp( host, (WCHAR *)((char *)map + value[i].NameOffset), len ) && !host[len])
+ {
+ value += i;
+ break;
+ }
+ }
+ }
+ if (!value->ValueOffset) return STATUS_DLL_NOT_FOUND;
+ ret->Buffer = (WCHAR *)((char *)map + value->ValueOffset);
+ ret->Length = value->ValueLength;
+ return STATUS_SUCCESS;
+}
+
+
/**********************************************************************
* build_import_name
*/
static NTSTATUS build_import_name( WCHAR buffer[256], const char *import, int len )
{
+ const API_SET_NAMESPACE *map = NtCurrentTeb()->Peb->ApiSetMap;
+ const API_SET_NAMESPACE_ENTRY *entry;
+ const WCHAR *host = current_modref ? current_modref->ldr.BaseDllName.Buffer : NULL;
+ UNICODE_STRING str;
+
while (len && import[len-1] == ' ') len--; /* remove trailing spaces */
if (len + sizeof(".dll") > 256) return STATUS_DLL_NOT_FOUND;
ascii_to_unicode( buffer, import, len );
buffer[len] = 0;
if (!wcschr( buffer, '.' )) wcscpy( buffer + len, L".dll" );
+
+ if (get_apiset_entry( map, buffer, wcslen(buffer), &entry )) return STATUS_SUCCESS;
+
+ if (get_apiset_target( map, entry, host, &str )) return STATUS_DLL_NOT_FOUND;
+ if (str.Length >= 256 * sizeof(WCHAR)) return STATUS_DLL_NOT_FOUND;
+
+ TRACE( "found %s for %s\n", debugstr_us(&str), debugstr_w(buffer));
+ memcpy( buffer, str.Buffer, str.Length );
+ buffer[str.Length / sizeof(WCHAR)] = 0;
return STATUS_SUCCESS;
}
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
index 98a5c933215..ab12a4ea1c0 100644
--- a/dlls/ntdll/unix/loader.c
+++ b/dlls/ntdll/unix/loader.c
@@ -2055,7 +2055,6 @@ static void load_apiset_dll(void)
{
NtCurrentTeb()->Peb->ApiSetMap = map;
if (wow_peb) wow_peb->ApiSetMap = PtrToUlong(map);
- NtUnmapViewOfSection( NtCurrentProcess(), ptr );
TRACE( "loaded %s apiset at %p\n", debugstr_w(path), map );
return;
}
More information about the wine-cvs
mailing list