Моя программа загружает несколько библиотек и вызывает их функции. DLL могут использовать разные версии CRT.
Когда среда выполнения C проверяет правильность аргументов и обнаруживает проблемы, она вызывает недопустимый дескриптор параметра, который, в свою очередь, закрывает приложение с или без диалога «Send-Don't send».
Я пытался вызвать * _set_invalid_parameter_handler *, но он работает только в том случае, если он вызывается из плохой библиотеки DLL. Я попытался SetErrorMode , но все, что мне удалось сделать, - убить процесс без диалога.
Есть ли способ обработать эти исключения? Мне все равно, если некоторые ресурсы скомпрометированы. Все, что я хочу, это разрешить пользователям сохранять конфигурацию. Если диалоговое окно появляется, они щелкают по нему и убивают процесс.
EDIT
Оказывается, решение загрузить все версии CRT или перечислить все библиотеки DLL не удается. Чтобы прояснить ситуацию, вот небольшой пример для игры:
Это будет мое основное приложение (давайте назовем файл application.c ):
#include <windows.h>
void myInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved) {
wprintf(L"Invalid parameter detected in function %s. File: %s Line: %d\n", function, file, line);
wprintf(L"Expression: %s\n", expression);
}
void fixMyProblem() {
}
int main(int argc, char **argv) {
HMODULE hModule = LoadLibrary("extension.dll");
void (WINAPI *function)() = GetProcAddress(hModule, "function");
fixMyProblem();
function();
}
Это приложение загружает dll, которая делает плохие вещи (оно не разработано мной, поэтому я не приму никакого решения, говорящего мне, чтобы исправить ошибки там). Позволяет вызвать этот файл extension.c .
#include <stdio.h>
__declspec(dllexport) void function() {
printf("do bad stuff");
fopen(NULL, "r");
}
Для компиляции выполните:
cl extension.c /link /OUT:extension.dll /DLL
cl application.c
Вопрос в том, что мне делать в функции fixMyProblem () , чтобы я не получил диалоговое окно отправить / не отправить в XP или приложение перестало работать диалоговое окно 7.
По словам Дэвида Гладфелтера, я должен сделать
void fixMyProblem() {
_set_invalid_parameter_handler(myInvalidParameterHandler);
}
, а также сделать это для каждой версии ЭЛТ. Оказывается, что даже с одной версией CRT (я использую одну и ту же для exe и dll), она все равно не работает. Они оба используют одинаковую версию ЭЛТ, но, похоже, они не используют одинаковую ЭЛТ.
Если это так, я предполагаю, что материал, который я должен изменить, находится внутри DLL. Конечно, он не экспортирует * _set_invalid_parameter_handler *.
Но, если честно, Дэвид Хеффернан, вот реализация его решения:
#include <Psapi.h>
#pragma comment(lib, "Psapi.lib")
void fixMyProblem() {
HANDLE hProcess = GetCurrentProcess();
HMODULE *hModules;
DWORD requiredSize = 0;
DWORD secondRequiredSize = 0;
if (!EnumProcessModules(hProcess, NULL, 0, &requiredSize)) {
printf("oops\n");
return;
}
hModules = malloc(requiredSize);
if (EnumProcessModules(hProcess, hModules, requiredSize, &secondRequiredSize)) {
int i;
int loadedModules = min(requiredSize, secondRequiredSize) / sizeof(HMODULE);
for (i = 0; i < loadedModules; i++) {
void *(WINAPI *_set_invalid_parameter_handler_function)(void *) = (void *(WINAPI *)(void *)) GetProcAddress(hModules[i], "_set_invalid_parameter_handler");
if (_set_invalid_parameter_handler_function != NULL) {
_set_invalid_parameter_handler_function(myInvalidParameterHandler);
printf("fixed dll %d\n", i);
}
}
} else {
printf("oops\n");
}
free(hModules);
}
Для моего реального приложения, а не для этого теста, я исправляю 1 dll (msvcp90.dll). Это все еще не решает мою проблему.
Буду признателен за помощь в решении этой проблемы.