构建没有CRT和控制台的控制台应用程序默认标头?

时间:2008-11-20 11:59:01

标签: c++ windows visual-studio-2008 visual-c++

我正在尝试在不使用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,这显然与CRT有关。 所以我想知道如何重写入口点的默认int wmain(int argc, wchar_t* argv[]),以及如何摆脱安全cookie。

6 个答案:

答案 0 :(得分:4)

_wmainCRTStartup是调用wmain()

的函数

IIRC它应该可以在你可以链接的某个.o文件中找到,查看你的lib目录。

也许这也很有用:Reduce EXE and DLL Size with LIBCTINY.LIB (和Matt Pietrek摇滚: - )

答案 1 :(得分:3)

好吧,在这里回答自己总结,以防其他人发现此页面正在寻找信息。

正如MSalters建议的那样,安全cookie代码可以从CRT源中窃取,但这样做我发现/GS-编译器标志可以用来完全避免安全性。

正如SoapBox所说,API函数需要__stdcall,以及入口点。 我用链接器命令行标志/entry:wmain修复了入口点问题。

最后,正如Tomek指出的那样,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;
}

答案 2 :(得分:2)

更正确的入口点声明将是:

int __stdcall wmain(PVOID ThreadParam)

没有由BaseThreadInitThunk直接调用的CRT入口点。它传递指向某事物的指针,但不是argc + argv。

答案 3 :(得分:1)

您可以在Windows.h中查看kernel32导入所需的原型。通常,Windows函数定义为WINAPI,实际上是__stdcall而不是__cdecl。这至少会解决这个问题。

至于你的另一个问题,你需要探索链接器命令行参数,看看是否有办法让它不从CRT中寻找东西。我不知道是否有办法做到这一点。但是你必须找到一种方法或者定义你自己的那些功能(你可能不想这样做)。

我建议只使用不同的编译器/链接器。

答案 4 :(得分:1)

您需要将windows.h函数声明为extern“C”。

答案 5 :(得分:0)

正确的入口点是main(),而不是wmain()(因为您正在编译控制台应用程序)。 安全cookie代码可以从CRT源代码中删除;无需将其链接。