Merge pull request #6848 from obsproject/plugin-warning
Add plugin load failure warning on startup
This commit is contained in:
commit
ec3ea46516
@ -113,6 +113,10 @@ MoveSourceDown="Move Source(s) Down"
|
||||
SourceProperties="Open Source Properties"
|
||||
SourceFilters="Open Source Filters"
|
||||
|
||||
# warning for plugin load failures
|
||||
PluginsFailedToLoad.Title="Plugin Load Error"
|
||||
PluginsFailedToLoad.Text="The following OBS plugins failed to load:\n\n%1\nPlease update or remove these plugins."
|
||||
|
||||
# warning if program already open
|
||||
AlreadyRunning.Title="OBS is already running"
|
||||
AlreadyRunning.Text="OBS is already running! Unless you meant to do this, please shut down any existing instances of OBS before trying to run a new instance. If you have OBS set to minimize to the system tray, please check to see if it's still running there."
|
||||
|
@ -1778,15 +1778,18 @@ void OBSBasic::OBSInit()
|
||||
LoadLibraryW(L"Qt6Network");
|
||||
#endif
|
||||
#endif
|
||||
struct obs_module_failure_info mfi;
|
||||
|
||||
AddExtraModulePaths();
|
||||
blog(LOG_INFO, "---------------------------------");
|
||||
obs_load_all_modules();
|
||||
obs_load_all_modules2(&mfi);
|
||||
blog(LOG_INFO, "---------------------------------");
|
||||
obs_log_loaded_modules();
|
||||
blog(LOG_INFO, "---------------------------------");
|
||||
obs_post_load_modules();
|
||||
|
||||
BPtr<char *> failed_modules = mfi.failed_modules;
|
||||
|
||||
#ifdef BROWSER_AVAILABLE
|
||||
cef = obs_browser_init_panel();
|
||||
#endif
|
||||
@ -2071,6 +2074,25 @@ void OBSBasic::OBSInit()
|
||||
OnFirstLoad();
|
||||
|
||||
activateWindow();
|
||||
|
||||
/* ------------------------------------------- */
|
||||
/* display warning message for failed modules */
|
||||
|
||||
if (mfi.count) {
|
||||
QString failed_plugins;
|
||||
|
||||
char **plugin = mfi.failed_modules;
|
||||
while (*plugin) {
|
||||
failed_plugins += *plugin;
|
||||
failed_plugins += "\n";
|
||||
plugin++;
|
||||
}
|
||||
|
||||
QString failed_msg =
|
||||
QTStr("PluginsFailedToLoad.Text").arg(failed_plugins);
|
||||
OBSMessageBox::warning(this, QTStr("PluginsFailedToLoad.Title"),
|
||||
failed_msg);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasic::OnFirstLoad()
|
||||
|
@ -246,6 +246,36 @@ plugin modules.
|
||||
|
||||
---------------------
|
||||
|
||||
.. function:: void obs_load_all_modules2(struct obs_module_failure_info *mfi)
|
||||
|
||||
Automatically loads all modules from module paths (convenience function).
|
||||
Additionally gives you information about modules that fail to load.
|
||||
|
||||
:param mfi: Provides module failure information. The *failed_modules*
|
||||
member is a string list via a pointer to pointers of
|
||||
strings of modules that failed to load. Can be freed
|
||||
either with :c:func:`obs_module_failure_info_free()` or
|
||||
by simply calling :c:func:`bfree()` on the
|
||||
*failed_modules* member variable.
|
||||
|
||||
Relevant data types used with this function:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
struct obs_module_failure_info {
|
||||
char **failed_modules;
|
||||
size_t count;
|
||||
};
|
||||
|
||||
---------------------
|
||||
|
||||
.. function:: void obs_module_failure_info_free(struct obs_module_failure_info *mfi)
|
||||
|
||||
Frees data allocated data used in the *mfi* parameter (calls
|
||||
:c:func:`bfree()` on the *failed_modules* member variable).
|
||||
|
||||
---------------------
|
||||
|
||||
.. function:: void obs_post_load_modules(void)
|
||||
|
||||
Notifies modules that all modules have been loaded.
|
||||
@ -271,6 +301,26 @@ plugin modules.
|
||||
|
||||
---------------------
|
||||
|
||||
.. function:: void obs_find_modules2(obs_find_module_callback_t callback, void *param)
|
||||
|
||||
Finds all modules within the search paths added by
|
||||
:c:func:`obs_add_module_path()`.
|
||||
|
||||
Relevant data types used with this function:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
struct obs_module_info2 {
|
||||
const char *bin_path;
|
||||
const char *data_path;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
typedef void (*obs_find_module_callback2_t)(void *param,
|
||||
const struct obs_module_info2 *info);
|
||||
|
||||
---------------------
|
||||
|
||||
.. function:: void obs_enum_modules(obs_enum_module_callback_t callback, void *param)
|
||||
|
||||
Enumerates all loaded modules.
|
||||
|
@ -11,6 +11,12 @@ find_package(
|
||||
OPTIONAL_COMPONENTS avcodec)
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
if(ENABLE_UI)
|
||||
find_qt(COMPONENTS Core)
|
||||
else()
|
||||
set(_QT_VERSION 0)
|
||||
endif()
|
||||
|
||||
add_library(libobs SHARED)
|
||||
add_library(OBS::libobs ALIAS libobs)
|
||||
|
||||
|
@ -274,27 +274,55 @@ void obs_add_module_path(const char *bin, const char *data)
|
||||
da_push_back(obs->module_paths, &omp);
|
||||
}
|
||||
|
||||
static void load_all_callback(void *param, const struct obs_module_info *info)
|
||||
extern void get_plugin_info(const char *path, bool *is_obs_plugin,
|
||||
bool *can_load);
|
||||
|
||||
struct fail_info {
|
||||
struct dstr fail_modules;
|
||||
size_t fail_count;
|
||||
};
|
||||
|
||||
static void load_all_callback(void *param, const struct obs_module_info2 *info)
|
||||
{
|
||||
struct fail_info *fail_info = param;
|
||||
obs_module_t *module;
|
||||
|
||||
if (!os_is_obs_plugin(info->bin_path)) {
|
||||
bool is_obs_plugin;
|
||||
bool can_load_obs_plugin;
|
||||
|
||||
get_plugin_info(info->bin_path, &is_obs_plugin, &can_load_obs_plugin);
|
||||
|
||||
if (!is_obs_plugin) {
|
||||
blog(LOG_WARNING, "Skipping module '%s', not an OBS plugin",
|
||||
info->bin_path);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!can_load_obs_plugin) {
|
||||
blog(LOG_WARNING, "Skipping module '%s' due to possible "
|
||||
"import conflicts");
|
||||
goto load_failure;
|
||||
}
|
||||
|
||||
int code = obs_open_module(&module, info->bin_path, info->data_path);
|
||||
if (code != MODULE_SUCCESS) {
|
||||
blog(LOG_DEBUG, "Failed to load module file '%s': %d",
|
||||
info->bin_path, code);
|
||||
return;
|
||||
goto load_failure;
|
||||
}
|
||||
|
||||
if (!obs_init_module(module))
|
||||
free_module(module);
|
||||
|
||||
UNUSED_PARAMETER(param);
|
||||
return;
|
||||
|
||||
load_failure:
|
||||
if (fail_info) {
|
||||
dstr_cat(&fail_info->fail_modules, info->name);
|
||||
dstr_cat(&fail_info->fail_modules, ";");
|
||||
fail_info->fail_count++;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *obs_load_all_modules_name = "obs_load_all_modules";
|
||||
@ -305,7 +333,7 @@ static const char *reset_win32_symbol_paths_name = "reset_win32_symbol_paths";
|
||||
void obs_load_all_modules(void)
|
||||
{
|
||||
profile_start(obs_load_all_modules_name);
|
||||
obs_find_modules(load_all_callback, NULL);
|
||||
obs_find_modules2(load_all_callback, NULL);
|
||||
#ifdef _WIN32
|
||||
profile_start(reset_win32_symbol_paths_name);
|
||||
reset_win32_symbol_paths();
|
||||
@ -314,6 +342,36 @@ void obs_load_all_modules(void)
|
||||
profile_end(obs_load_all_modules_name);
|
||||
}
|
||||
|
||||
static const char *obs_load_all_modules2_name = "obs_load_all_modules2";
|
||||
|
||||
void obs_load_all_modules2(struct obs_module_failure_info *mfi)
|
||||
{
|
||||
struct fail_info fail_info = {0};
|
||||
memset(mfi, 0, sizeof(*mfi));
|
||||
|
||||
profile_start(obs_load_all_modules2_name);
|
||||
obs_find_modules2(load_all_callback, &fail_info);
|
||||
#ifdef _WIN32
|
||||
profile_start(reset_win32_symbol_paths_name);
|
||||
reset_win32_symbol_paths();
|
||||
profile_end(reset_win32_symbol_paths_name);
|
||||
#endif
|
||||
profile_end(obs_load_all_modules2_name);
|
||||
|
||||
mfi->count = fail_info.fail_count;
|
||||
mfi->failed_modules =
|
||||
strlist_split(fail_info.fail_modules.array, ';', false);
|
||||
dstr_free(&fail_info.fail_modules);
|
||||
}
|
||||
|
||||
void obs_module_failure_info_free(struct obs_module_failure_info *mfi)
|
||||
{
|
||||
if (mfi->failed_modules) {
|
||||
bfree(mfi->failed_modules);
|
||||
mfi->failed_modules = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void obs_post_load_modules(void)
|
||||
{
|
||||
for (obs_module_t *mod = obs->first_module; !!mod; mod = mod->next)
|
||||
@ -388,10 +446,10 @@ static bool parse_binary_from_directory(struct dstr *parsed_bin_path,
|
||||
|
||||
static void process_found_module(struct obs_module_path *omp, const char *path,
|
||||
bool directory,
|
||||
obs_find_module_callback_t callback,
|
||||
obs_find_module_callback2_t callback,
|
||||
void *param)
|
||||
{
|
||||
struct obs_module_info info;
|
||||
struct obs_module_info2 info;
|
||||
struct dstr name = {0};
|
||||
struct dstr parsed_bin_path = {0};
|
||||
const char *file;
|
||||
@ -421,6 +479,7 @@ static void process_found_module(struct obs_module_path *omp, const char *path,
|
||||
if (parsed_data_dir && bin_found) {
|
||||
info.bin_path = parsed_bin_path.array;
|
||||
info.data_path = parsed_data_dir;
|
||||
info.name = name.array;
|
||||
callback(param, &info);
|
||||
}
|
||||
|
||||
@ -430,7 +489,7 @@ static void process_found_module(struct obs_module_path *omp, const char *path,
|
||||
}
|
||||
|
||||
static void find_modules_in_path(struct obs_module_path *omp,
|
||||
obs_find_module_callback_t callback,
|
||||
obs_find_module_callback2_t callback,
|
||||
void *param)
|
||||
{
|
||||
struct dstr search_path = {0};
|
||||
@ -467,7 +526,7 @@ static void find_modules_in_path(struct obs_module_path *omp,
|
||||
dstr_free(&search_path);
|
||||
}
|
||||
|
||||
void obs_find_modules(obs_find_module_callback_t callback, void *param)
|
||||
void obs_find_modules2(obs_find_module_callback2_t callback, void *param)
|
||||
{
|
||||
if (!obs)
|
||||
return;
|
||||
@ -478,6 +537,12 @@ void obs_find_modules(obs_find_module_callback_t callback, void *param)
|
||||
}
|
||||
}
|
||||
|
||||
void obs_find_modules(obs_find_module_callback_t callback, void *param)
|
||||
{
|
||||
/* the structure is ABI compatible so we can just cast the callback */
|
||||
obs_find_modules2((obs_find_module_callback2_t)callback, param);
|
||||
}
|
||||
|
||||
void obs_enum_modules(obs_enum_module_callback_t callback, void *param)
|
||||
{
|
||||
struct obs_module *module;
|
||||
|
23
libobs/obs.h
23
libobs/obs.h
@ -506,6 +506,7 @@ EXPORT const char *obs_get_module_binary_path(obs_module_t *module);
|
||||
/** Returns the module data path */
|
||||
EXPORT const char *obs_get_module_data_path(obs_module_t *module);
|
||||
|
||||
#ifndef SWIG
|
||||
/**
|
||||
* Adds a module search path to be used with obs_find_modules. If the search
|
||||
* path strings contain %module%, that text will be replaced with the module
|
||||
@ -519,11 +520,18 @@ EXPORT void obs_add_module_path(const char *bin, const char *data);
|
||||
/** Automatically loads all modules from module paths (convenience function) */
|
||||
EXPORT void obs_load_all_modules(void);
|
||||
|
||||
struct obs_module_failure_info {
|
||||
char **failed_modules;
|
||||
size_t count;
|
||||
};
|
||||
|
||||
EXPORT void obs_module_failure_info_free(struct obs_module_failure_info *mfi);
|
||||
EXPORT void obs_load_all_modules2(struct obs_module_failure_info *mfi);
|
||||
|
||||
/** Notifies modules that all modules have been loaded. This function should
|
||||
* be called after all modules have been loaded. */
|
||||
EXPORT void obs_post_load_modules(void);
|
||||
|
||||
#ifndef SWIG
|
||||
struct obs_module_info {
|
||||
const char *bin_path;
|
||||
const char *data_path;
|
||||
@ -534,6 +542,19 @@ typedef void (*obs_find_module_callback_t)(void *param,
|
||||
|
||||
/** Finds all modules within the search paths added by obs_add_module_path. */
|
||||
EXPORT void obs_find_modules(obs_find_module_callback_t callback, void *param);
|
||||
|
||||
struct obs_module_info2 {
|
||||
const char *bin_path;
|
||||
const char *data_path;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
typedef void (*obs_find_module_callback2_t)(
|
||||
void *param, const struct obs_module_info2 *info);
|
||||
|
||||
/** Finds all modules within the search paths added by obs_add_module_path. */
|
||||
EXPORT void obs_find_modules2(obs_find_module_callback2_t callback,
|
||||
void *param);
|
||||
#endif
|
||||
|
||||
typedef void (*obs_enum_module_callback_t)(void *param, obs_module_t *module);
|
||||
|
@ -14,6 +14,7 @@
|
||||
#define OBS_DATA_PATH "@OBS_DATA_PATH@"
|
||||
#define OBS_INSTALL_PREFIX "@OBS_INSTALL_PREFIX@"
|
||||
#define OBS_PLUGIN_DESTINATION "@OBS_PLUGIN_DESTINATION@"
|
||||
#define OBS_QT_VERSION @_QT_VERSION@
|
||||
|
||||
#cmakedefine LINUX_PORTABLE
|
||||
#cmakedefine GIO_FOUND
|
||||
|
@ -96,6 +96,13 @@ void os_dlclose(void *module)
|
||||
dlclose(module);
|
||||
}
|
||||
|
||||
void get_plugin_info(const char *path, bool *is_obs_plugin, bool *can_load)
|
||||
{
|
||||
*is_obs_plugin = true;
|
||||
*can_load = true;
|
||||
UNUSED_PARAMETER(path);
|
||||
}
|
||||
|
||||
bool os_is_obs_plugin(const char *path)
|
||||
{
|
||||
UNUSED_PARAMETER(path);
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "platform.h"
|
||||
#include "darray.h"
|
||||
#include "dstr.h"
|
||||
#include "obsconfig.h"
|
||||
#include "util_uint64.h"
|
||||
#include "windows/win-registry.h"
|
||||
#include "windows/win-version.h"
|
||||
@ -136,7 +137,145 @@ void os_dlclose(void *module)
|
||||
FreeLibrary(module);
|
||||
}
|
||||
|
||||
bool os_is_obs_plugin(const char *path)
|
||||
#if OBS_QT_VERSION == 6
|
||||
static bool has_qt5_import(VOID *base, PIMAGE_NT_HEADERS nt_headers)
|
||||
{
|
||||
__try {
|
||||
PIMAGE_DATA_DIRECTORY data_dir;
|
||||
data_dir =
|
||||
&nt_headers->OptionalHeader
|
||||
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
|
||||
if (data_dir->Size == 0)
|
||||
return false;
|
||||
|
||||
PIMAGE_SECTION_HEADER section, last_section;
|
||||
section = IMAGE_FIRST_SECTION(nt_headers);
|
||||
last_section = section;
|
||||
|
||||
/* find the section that contains the export directory */
|
||||
int i;
|
||||
for (i = 0; i < nt_headers->FileHeader.NumberOfSections; i++) {
|
||||
if (section->VirtualAddress <=
|
||||
data_dir->VirtualAddress) {
|
||||
last_section = section;
|
||||
section++;
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* double check in case we exited early */
|
||||
if (last_section->VirtualAddress > data_dir->VirtualAddress ||
|
||||
section->VirtualAddress <= data_dir->VirtualAddress)
|
||||
return false;
|
||||
|
||||
section = last_section;
|
||||
|
||||
/* get a pointer to the import directory */
|
||||
PIMAGE_IMPORT_DESCRIPTOR import;
|
||||
import = (PIMAGE_IMPORT_DESCRIPTOR)((byte *)base +
|
||||
data_dir->VirtualAddress -
|
||||
section->VirtualAddress +
|
||||
section->PointerToRawData);
|
||||
|
||||
while (import->Name != 0) {
|
||||
char *name = (char *)((byte *)base + import->Name -
|
||||
section->VirtualAddress +
|
||||
section->PointerToRawData);
|
||||
|
||||
/* qt5? bingo, reject this library */
|
||||
if (astrcmpi_n(name, "qt5", 3) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
import++;
|
||||
}
|
||||
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
/* we failed somehow, for compatibility assume no qt5 import */
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool has_obs_export(VOID *base, PIMAGE_NT_HEADERS nt_headers)
|
||||
{
|
||||
__try {
|
||||
PIMAGE_DATA_DIRECTORY data_dir;
|
||||
data_dir =
|
||||
&nt_headers->OptionalHeader
|
||||
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
|
||||
|
||||
if (data_dir->Size == 0)
|
||||
return false;
|
||||
|
||||
PIMAGE_SECTION_HEADER section, last_section;
|
||||
section = IMAGE_FIRST_SECTION(nt_headers);
|
||||
last_section = section;
|
||||
|
||||
/* find the section that contains the export directory */
|
||||
int i;
|
||||
for (i = 0; i < nt_headers->FileHeader.NumberOfSections; i++) {
|
||||
if (section->VirtualAddress <=
|
||||
data_dir->VirtualAddress) {
|
||||
last_section = section;
|
||||
section++;
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* double check in case we exited early */
|
||||
if (last_section->VirtualAddress > data_dir->VirtualAddress ||
|
||||
section->VirtualAddress <= data_dir->VirtualAddress)
|
||||
return false;
|
||||
|
||||
section = last_section;
|
||||
|
||||
/* get a pointer to the export directory */
|
||||
PIMAGE_EXPORT_DIRECTORY export;
|
||||
export = (PIMAGE_EXPORT_DIRECTORY)((byte *)base +
|
||||
data_dir->VirtualAddress -
|
||||
section->VirtualAddress +
|
||||
section->PointerToRawData);
|
||||
|
||||
if (export->NumberOfNames == 0)
|
||||
return false;
|
||||
|
||||
/* get a pointer to the export directory names */
|
||||
DWORD *names_ptr;
|
||||
names_ptr = (DWORD *)((byte *)base + export->AddressOfNames -
|
||||
section->VirtualAddress +
|
||||
section->PointerToRawData);
|
||||
|
||||
/* iterate through each name and see if its an obs plugin */
|
||||
CHAR *name;
|
||||
size_t j;
|
||||
for (j = 0; j < export->NumberOfNames; j++) {
|
||||
|
||||
name = (CHAR *)base + names_ptr[j] -
|
||||
section->VirtualAddress +
|
||||
section->PointerToRawData;
|
||||
|
||||
if (!strcmp(name, "obs_module_load")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
/* we failed somehow, for compatibility let's assume it
|
||||
* was a valid plugin and let the loader deal with it */
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void get_plugin_info(const char *path, bool *is_obs_plugin, bool *can_load)
|
||||
{
|
||||
struct dstr dll_name;
|
||||
wchar_t *wpath;
|
||||
@ -147,12 +286,12 @@ bool os_is_obs_plugin(const char *path)
|
||||
|
||||
PIMAGE_DOS_HEADER dos_header;
|
||||
PIMAGE_NT_HEADERS nt_headers;
|
||||
PIMAGE_SECTION_HEADER section, last_section;
|
||||
|
||||
bool ret = false;
|
||||
*is_obs_plugin = false;
|
||||
*can_load = false;
|
||||
|
||||
if (!path)
|
||||
return false;
|
||||
return;
|
||||
|
||||
dstr_init_copy(&dll_name, path);
|
||||
dstr_replace(&dll_name, "\\", "/");
|
||||
@ -193,72 +332,21 @@ bool os_is_obs_plugin(const char *path)
|
||||
if (nt_headers->Signature != IMAGE_NT_SIGNATURE)
|
||||
goto cleanup;
|
||||
|
||||
PIMAGE_DATA_DIRECTORY data_dir;
|
||||
data_dir =
|
||||
&nt_headers->OptionalHeader
|
||||
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
|
||||
*is_obs_plugin = has_obs_export(base, nt_headers);
|
||||
|
||||
if (data_dir->Size == 0)
|
||||
goto cleanup;
|
||||
|
||||
section = IMAGE_FIRST_SECTION(nt_headers);
|
||||
last_section = section;
|
||||
|
||||
/* find the section that contains the export directory */
|
||||
int i;
|
||||
for (i = 0; i < nt_headers->FileHeader.NumberOfSections; i++) {
|
||||
if (section->VirtualAddress <=
|
||||
data_dir->VirtualAddress) {
|
||||
last_section = section;
|
||||
section++;
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* double check in case we exited early */
|
||||
if (last_section->VirtualAddress > data_dir->VirtualAddress ||
|
||||
section->VirtualAddress <= data_dir->VirtualAddress)
|
||||
goto cleanup;
|
||||
|
||||
section = last_section;
|
||||
|
||||
/* get a pointer to the export directory */
|
||||
PIMAGE_EXPORT_DIRECTORY export;
|
||||
export = (PIMAGE_EXPORT_DIRECTORY)((byte *)base +
|
||||
data_dir->VirtualAddress -
|
||||
section->VirtualAddress +
|
||||
section->PointerToRawData);
|
||||
|
||||
if (export->NumberOfNames == 0)
|
||||
goto cleanup;
|
||||
|
||||
/* get a pointer to the export directory names */
|
||||
DWORD *names_ptr;
|
||||
names_ptr = (DWORD *)((byte *)base + export->AddressOfNames -
|
||||
section->VirtualAddress +
|
||||
section->PointerToRawData);
|
||||
|
||||
/* iterate through each name and see if its an obs plugin */
|
||||
CHAR *name;
|
||||
size_t j;
|
||||
for (j = 0; j < export->NumberOfNames; j++) {
|
||||
|
||||
name = (CHAR *)base + names_ptr[j] -
|
||||
section->VirtualAddress +
|
||||
section->PointerToRawData;
|
||||
|
||||
if (!strcmp(name, "obs_module_load")) {
|
||||
ret = true;
|
||||
goto cleanup;
|
||||
}
|
||||
#if OBS_QT_VERSION == 6
|
||||
if (*is_obs_plugin) {
|
||||
*can_load = !has_qt5_import(base, nt_headers);
|
||||
}
|
||||
#else
|
||||
*can_load = true;
|
||||
#endif
|
||||
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
/* we failed somehow, for compatibility let's assume it
|
||||
* was a valid plugin and let the loader deal with it */
|
||||
ret = true;
|
||||
*is_obs_plugin = true;
|
||||
*can_load = true;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -271,8 +359,16 @@ cleanup:
|
||||
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
return ret;
|
||||
bool os_is_obs_plugin(const char *path)
|
||||
{
|
||||
bool is_obs_plugin;
|
||||
bool can_load;
|
||||
|
||||
get_plugin_info(path, &is_obs_plugin, &can_load);
|
||||
|
||||
return is_obs_plugin && can_load;
|
||||
}
|
||||
|
||||
union time_data {
|
||||
|
Loading…
x
Reference in New Issue
Block a user