Я пытаюсь создать консольное приложение без использования CRT или любого другого импорта, кроме kernel32.lib, в любом случае. Я получаю свой код для компиляции, но не могу решить несколько проблем с помощью компоновщика:
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[]) по умолчанию для точки входа и как избавиться от файлов cookie безопасности.





Вы можете заглянуть в Windows.h, чтобы увидеть прототипы, необходимые для импорта kernel32. В общем, функции Windows определены WINAPI, который на самом деле является __stdcall, а не __cdecl. По крайней мере, это решит эту проблему.
Что касается другой вашей проблемы, вам нужно изучить аргументы командной строки компоновщика и посмотреть, есть ли способ заставить его не искать что-то в CRT. Я не знаю, есть ли способ сделать это или нет. Но вам придется найти способ или самостоятельно определить эти функции (чего вы, вероятно, не хотите делать).
Я бы рекомендовал просто использовать другой компилятор / компоновщик.
Правильная точка входа - main(), а не wmain() (поскольку вы компилируете консольное приложение).
Код безопасности cookie может быть взят из исходного кода CRT; нет необходимости связывать это.
_wmainCRTStartup - это функция, которая вызывает wmain ()
IIRC, он должен быть доступен в каком-то файле .o, с которым вы можете связать, посмотрите в своем каталоге lib.
Может быть, это тоже полезно прочитать: Уменьшите размер EXE и DLL с помощью LIBCTINY.LIB (и Мэтт Питрек крут :-)
Вам необходимо объявить функции windows.h как extern «C».
Что ж, отвечу себе здесь, чтобы подвести итог, на случай, если кто-то еще найдет эту страницу в поисках информации.
Как советовал MSalters, код cookie безопасности можно украсть из источника CRT, но, сделав это, я обнаружил, что флаг компилятора /GS- можно использовать, чтобы полностью избежать проблем с безопасностью.
Как сказал SoapBox, функции API должны быть __stdcall, а также точка входа.
Я исправил проблему точки входа с флагом командной строки компоновщика /entry:wmain.
И, наконец, как указал Томек, функции API должны быть во внешнем 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;
}
Я как раз писал ответ, который включал опцию /entry, когда заметил, что в вашем собственном ответе есть почти все, кроме: 1. Включение windows.h не повредит размеру вашего исполняемого файла ни на бит. Используйте #define WIN32_LEAN_AND_MEAN и #define WIN32_EXTRA_LEAN, если хотите быть уверенными. Заголовки Win32 не включают заголовки CRT, поэтому здесь проблем не возникнет. 2. Вы, вероятно, уже делаете это, но передайте /NODEFAULTLIB компоновщику и сделайте ссылку на kernel32.lib и т. д. Вручную. Это действительно сильно снижает размер исполняемого файла.
Более правильное объявление точки входа будет:
int __stdcall wmain(PVOID ThreadParam)
Без точки входа CRT, вызываемой напрямую BaseThreadInitThunk. Он передает указатель на что-то, но не на argc + argv.
На самом деле я уже пробовал их как стандартные вызовы, и это не решило проблему.