Создание консольных приложений без заголовков CRT и default?
Я пытаюсь создать консольное приложение без использования CRT или любого другого импорта, кроме kernel32.во всяком случае, Либ. Я получаю свой код для компиляции, но не могу обернуть компоновщик вокруг нескольких проблем:
unresolved external symbol @__security_check_cookie@4
unresolved external symbol "int __cdecl FreeLibrary(void *)" (?FreeLibrary@@YAHPAX@Z)
unresolved external symbol "void * __cdecl LoadLibraryW(wchar_t *)" (?LoadLibraryW@@YAPAXPA_W@Z)
unresolved external symbol "int (__cdecl*__cdecl GetProcAddress(void *,char *))(void)" (?GetProcAddress@@YAP6AHXZPAXPAD@Z)
unresolved external symbol _wmainCRTStartup
FreeLibrary, LoadLibraryW и GetProcAddress я ввел в программу явно, не используя windows.h:
#pragma comment(lib, "kernel32.lib")
typedef int(*FARPROC)();
void* LoadLibraryW( wchar_t* lpLibFileName );
FARPROC GetProcAddress( void* hModule, char* lpProcName );
int FreeLibrary( void* hLibModule );
Я полагаю, что-то не так с моими прототипами.
Тем не менее, большая проблема __security_check_cookie
и _wmainCRTStartup
, которые, очевидно, что-то это связано с ЭЛТ.
Поэтому мне интересно, как я буду переопределять значение по умолчанию int wmain(int argc, wchar_t* argv[])
для entrypoint и как избавиться от любого файла cookie безопасности.
6 ответов
_wmainCRTStartup-это функция, которая вызывает wmain ()
IIRC он должен быть доступен в некоторых .o файл, с которым вы можете связаться, посмотрите в каталоге lib.
может быть, это тоже полезное чтение: уменьшить размер EXE и DLL с LIBCTINY.Либ!--6--> (и Matt Pietrek скалы :-)
Ну, отвечая себе здесь, чтобы подвести итог, в случае, если кто-то еще найдет эту страницу в поисках информации.
как советовал MSalters, код cookie безопасности может быть украден из источника CRT, но при этом я обнаружил, что /GS-
флаг компилятора можно использовать, чтобы полностью избежать безопасности.
как сказал SoapBox, функции API должны быть __stdcall
, а также точка входа не.
Я исправил проблему точки входа с флагом командной строки компоновщика /entry:wmain
.
и, наконец, как отметил Томек, функции API должны быть в extern C!
так:
#pragma comment(lib, "kernel32.lib")
typedef int(*FARPROC)();
extern "C" {
void* __stdcall LoadLibraryW( wchar_t* lpLibFileName );
FARPROC __stdcall GetProcAddress( void* hModule, char* lpProcName );
int __stdcall FreeLibrary( void* hLibModule );
typedef int (__stdcall *f_MessageBoxW_t)( unsigned long hWnd, wchar_t* lpText, wchar_t* lpCaption, unsigned long uType);
f_MessageBoxW_t fnMsg;
void* hUser;
};
int __stdcall wmain(int argc, wchar_t* argv[])
{
hUser = LoadLibraryW( L"user32.dll" );
fnMsg = (f_MessageBoxW_t)GetProcAddress( hUser, "MessageBoxW" );
fnMsg( 0, L"foo", L"bar", 0 );
FreeLibrary( hUser );
return 0;
}
более правильное объявление точки входа будет:
int __stdcall wmain(PVOID ThreadParam)
без точки входа CRT, вызываемой напрямую BaseThreadInitThunk. Его передает указатель на что-то, но не argc+argv.
вы можете посмотреть в Windows.h чтобы увидеть прототипы, необходимые для импорта kernel32. В общем случае функции windows определены WINAPI
что на самом деле __stdcall
, а не __cdecl
. По крайней мере, это решит проблему.
Что касается вашей другой проблемы, вам нужно изучить аргументы командной строки компоновщика и посмотреть, есть ли способ заставить его не искать вещи из CRT. Я не знаю, есть ли способ сделать это или нет. Но тебе придется найти способ или определение. это функции вашего " Я " (которые вы, вероятно, не хотите делать).
Я бы рекомендовал просто использовать другой компилятор / компоновщик.
правильная точка входа main()
, а не wmain()
(поскольку вы компилируете консольное приложение).
Код cookie безопасности может быть взят из исходного кода CRT; нет необходимости связывать его.