• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #ifndef COMPAT_W32DLFCN_H
20 #define COMPAT_W32DLFCN_H
21 
22 #ifdef _WIN32
23 #include <stdint.h>
24 
25 #include <windows.h>
26 
27 #include "config.h"
28 #include "libavutil/macros.h"
29 #include "libavutil/wchar_filename.h"
30 
get_module_filename(HMODULE module)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 
57 /**
58  * Safe function used to open dynamic libs. This attempts to improve program security
59  * by removing the current directory from the dll search path. Only dll's found in the
60  * executable or system directory are allowed to be loaded.
61  * @param name  The dynamic lib name.
62  * @return A handle to the opened lib.
63  */
win32_dlopen(const char * name)64 static inline HMODULE win32_dlopen(const char *name)
65 {
66     wchar_t *name_w;
67     HMODULE module = NULL;
68     if (utf8towchar(name, &name_w))
69         name_w = NULL;
70 #if _WIN32_WINNT < 0x0602
71     // On Win7 and earlier we check if KB2533623 is available
72     if (!GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "SetDefaultDllDirectories")) {
73         wchar_t *path = NULL, *new_path;
74         DWORD pathlen, pathsize, namelen;
75         if (!name_w)
76             goto exit;
77         namelen = wcslen(name_w);
78         // Try local directory first
79         path = get_module_filename(NULL);
80         if (!path)
81             goto exit;
82         new_path = wcsrchr(path, '\\');
83         if (!new_path)
84             goto exit;
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;
91         wcscpy(path + pathlen + 1, name_w);
92         module = LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
93         if (module == NULL) {
94             // Next try System32 directory
95             pathlen = GetSystemDirectoryW(path, pathsize);
96             if (!pathlen)
97                 goto exit;
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'\\';
113             wcscpy(path + pathlen + 1, name_w);
114             module = LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
115         }
116 exit:
117         av_free(path);
118         av_free(name_w);
119         return module;
120     }
121 #endif
122 #ifndef LOAD_LIBRARY_SEARCH_APPLICATION_DIR
123 #   define LOAD_LIBRARY_SEARCH_APPLICATION_DIR 0x00000200
124 #endif
125 #ifndef LOAD_LIBRARY_SEARCH_SYSTEM32
126 #   define LOAD_LIBRARY_SEARCH_SYSTEM32        0x00000800
127 #endif
128 #if HAVE_WINRT
129     if (!name_w)
130         return NULL;
131     module = LoadPackagedLibrary(name_w, 0);
132 #else
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
139 #endif
140     av_free(name_w);
141     return module;
142 }
143 #define dlopen(name, flags) win32_dlopen(name)
144 #define dlclose FreeLibrary
145 #define dlsym GetProcAddress
146 #else
147 #include <dlfcn.h>
148 #endif
149 
150 #endif /* COMPAT_W32DLFCN_H */
151