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