2020#define COMPAT_W32DLFCN_H
2121
2222#ifdef _WIN32
23+ #include <stdint.h>
24+
2325#include <windows.h>
26+
2427#include "config.h"
25- #if ( _WIN32_WINNT < 0x0602 ) || HAVE_WINRT
28+ #include "libavutil/macros.h"
2629#include "libavutil/wchar_filename.h"
27- #endif
30+
31+ static inline wchar_t * get_module_filename (HMODULE module )
32+ {
33+ wchar_t * path = NULL , * new_path ;
34+ DWORD path_size = 0 , path_len ;
35+
36+ do {
37+ path_size = path_size ? FFMIN (2 * path_size , INT16_MAX + 1 ) : MAX_PATH ;
38+ new_path = av_realloc_array (path , path_size , sizeof * path );
39+ if (!new_path ) {
40+ av_free (path );
41+ return NULL ;
42+ }
43+ path = new_path ;
44+ // Returns path_size in case of insufficient buffer.
45+ // Whether the error is set or not and whether the output
46+ // is null-terminated or not depends on the version of Windows.
47+ path_len = GetModuleFileNameW (module , path , path_size );
48+ } while (path_len && path_size <= INT16_MAX && path_size <= path_len );
49+
50+ if (!path_len ) {
51+ av_free (path );
52+ return NULL ;
53+ }
54+ return path ;
55+ }
56+
2857/**
2958 * Safe function used to open dynamic libs. This attempts to improve program security
3059 * by removing the current directory from the dll search path. Only dll's found in the
3463 */
3564static inline HMODULE win32_dlopen (const char * name )
3665{
66+ wchar_t * name_w ;
67+ HMODULE module = NULL ;
68+ if (utf8towchar (name , & name_w ))
69+ name_w = NULL ;
3770#if _WIN32_WINNT < 0x0602
38- // Need to check if KB2533623 is available
71+ // On Win7 and earlier we check if KB2533623 is available
3972 if (!GetProcAddress (GetModuleHandleW (L"kernel32.dll" ), "SetDefaultDllDirectories" )) {
40- HMODULE module = NULL ;
41- wchar_t * path = NULL , * name_w = NULL ;
42- DWORD pathlen ;
43- if (utf8towchar (name , & name_w ))
73+ wchar_t * path = NULL , * new_path ;
74+ DWORD pathlen , pathsize , namelen ;
75+ if (!name_w )
4476 goto exit ;
45- path = ( wchar_t * ) av_calloc ( MAX_PATH , sizeof ( wchar_t ) );
77+ namelen = wcslen ( name_w );
4678 // Try local directory first
47- pathlen = GetModuleFileNameW (NULL , path , MAX_PATH );
48- pathlen = wcsrchr (path , '\\' ) - path ;
49- if (pathlen == 0 || pathlen + wcslen (name_w ) + 2 > MAX_PATH )
79+ path = get_module_filename (NULL );
80+ if (!path )
81+ goto exit ;
82+ new_path = wcsrchr (path , '\\' );
83+ if (!new_path )
5084 goto exit ;
51- path [pathlen ] = '\\' ;
85+ pathlen = new_path - path ;
86+ pathsize = pathlen + namelen + 2 ;
87+ new_path = av_realloc_array (path , pathsize , sizeof * path );
88+ if (!new_path )
89+ goto exit ;
90+ path = new_path ;
5291 wcscpy (path + pathlen + 1 , name_w );
5392 module = LoadLibraryExW (path , NULL , LOAD_WITH_ALTERED_SEARCH_PATH );
5493 if (module == NULL ) {
5594 // Next try System32 directory
56- pathlen = GetSystemDirectoryW (path , MAX_PATH );
57- if (pathlen == 0 || pathlen + wcslen ( name_w ) + 2 > MAX_PATH )
95+ pathlen = GetSystemDirectoryW (path , pathsize );
96+ if (! pathlen )
5897 goto exit ;
59- path [pathlen ] = '\\' ;
98+ // Buffer is not enough in two cases:
99+ // 1. system directory + \ + module name
100+ // 2. system directory even without the module name.
101+ if (pathlen + namelen + 2 > pathsize ) {
102+ pathsize = pathlen + namelen + 2 ;
103+ new_path = av_realloc_array (path , pathsize , sizeof * path );
104+ if (!new_path )
105+ goto exit ;
106+ path = new_path ;
107+ // Query again to handle the case #2.
108+ pathlen = GetSystemDirectoryW (path , pathsize );
109+ if (!pathlen )
110+ goto exit ;
111+ }
112+ path [pathlen ] = L'\\' ;
60113 wcscpy (path + pathlen + 1 , name_w );
61114 module = LoadLibraryExW (path , NULL , LOAD_WITH_ALTERED_SEARCH_PATH );
62115 }
@@ -73,16 +126,19 @@ static inline HMODULE win32_dlopen(const char *name)
73126# define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
74127#endif
75128#if HAVE_WINRT
76- wchar_t * name_w = NULL ;
77- int ret ;
78- if (utf8towchar (name , & name_w ))
129+ if (!name_w )
79130 return NULL ;
80- ret = LoadPackagedLibrary (name_w , 0 );
81- av_free (name_w );
82- return ret ;
131+ module = LoadPackagedLibrary (name_w , 0 );
83132#else
84- return LoadLibraryExA (name , NULL , LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32 );
133+ #define LOAD_FLAGS (LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32)
134+ /* filename may be be in CP_ACP */
135+ if (!name_w )
136+ return LoadLibraryExA (name , NULL , LOAD_FLAGS );
137+ module = LoadLibraryExW (name_w , NULL , LOAD_FLAGS );
138+ #undef LOAD_FLAGS
85139#endif
140+ av_free (name_w );
141+ return module ;
86142}
87143#define dlopen (name , flags ) win32_dlopen(name)
88144#define dlclose FreeLibrary
0 commit comments