2008-11-20 20 views
7

Tôi đang cố gắng xây dựng một ứng dụng giao diện điều khiển mà không cần sử dụng CRT hoặc bất kỳ nhập nào khác so với kernel32.lib trong mọi trường hợp. Tôi nhận được mã của tôi để biên dịch, nhưng không thể quấn mối liên kết xung quanh một số vấn đề:Xây dựng ứng dụng bảng điều khiển không có CRT và tiêu đề mặc định?

unresolved external symbol @[email protected] 
unresolved external symbol "int __cdecl FreeLibrary(void *)" ([email protected]@[email protected]) 
unresolved external symbol "void * __cdecl LoadLibraryW(wchar_t *)" ([email protected]@[email protected]) 
unresolved external symbol "int (__cdecl*__cdecl GetProcAddress(void *,char *))(void)" ([email protected]@[email protected]) 
unresolved external symbol _wmainCRTStartup 

FreeLibrary, LoadLibraryW và GetProcAddress tôi đã đưa vào chương trình một cách rõ ràng, không sử dụng 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); 

Tôi cho rằng có gì đó không ổn với nguyên mẫu của mình. Tuy nhiên, vấn đề lớn hơn là __security_check_cookie_wmainCRTStartup, rõ ràng là có liên quan đến CRT. Vì vậy, tôi tự hỏi làm thế nào tôi sẽ đi về trọng số mặc định int wmain(int argc, wchar_t* argv[]) cho entrypoint, và làm thế nào để thoát khỏi bất cứ điều gì các cookie bảo mật.

Trả lời

4

_wmainCRTStartup là chức năng mà các cuộc gọi wmain()

IIRC nó nên có sẵn trong một số tập tin .o mà bạn có thể liên kết với, tìm trong thư mục lib của bạn.

Có lẽ đây là bài đọc hữu ích quá: Reduce EXE and DLL Size with LIBCTINY.LIB (và Matt Pietrek đá :-)

1

Bạn có thể tìm trong Windows.h để xem các nguyên mẫu bạn cần cho nhập kernel32 của mình. Nói chung, các chức năng cửa sổ được xác định WINAPI thực tế là __stdcall và không phải là __cdecl. Điều đó sẽ khắc phục vấn đề đó ít nhất.

Đối với vấn đề khác của bạn, bạn cần phải khám phá các đối số dòng lệnh trình liên kết và xem có cách nào để làm cho nó không tìm kiếm những thứ từ CRT. Tôi không biết liệu có cách nào để làm điều đó hay không. Nhưng bạn sẽ phải tìm một cách hoặc xác định những chức năng tự của bạn (mà bạn có thể không muốn làm).

Tôi khuyên bạn chỉ nên sử dụng trình biên dịch/trình liên kết khác.

+0

Thực ra tôi đã thử chúng với tư cách là stdcalls, và nó không giải quyết được vấn đề. – anon6439

0

Điểm vào thích hợp là main(), không phải wmain() (vì bạn đang biên soạn ứng dụng bảng điều khiển). Mã cookie bảo mật có thể được lấy từ mã nguồn CRT; không cần phải liên kết nó trong.

+0

wmain là điểm vào giao diện điều khiển cho unicode. – anon6439

1

Bạn cần phải khai báo chức năng windows.h như extern "C".

+0

Cảm ơn bạn! Điều này giải quyết nó. – anon6439

3

Vâng, hãy tự trả lời ở đây để tổng hợp, trong trường hợp ai đó tìm thấy trang này đang tìm kiếm thông tin.

Theo MSalters, mã cookie bảo mật có thể bị lấy cắp từ nguồn CRT, nhưng làm như vậy tôi thấy rằng cờ biên dịch /GS- có thể được sử dụng để tránh toàn bộ công cụ bảo mật.

Như SoapBox đã nói, các hàm API cần phải là __stdcall, cũng như điểm vào. Tôi đã khắc phục sự cố điểm nhập với cờ dòng lệnh liên kết /entry:wmain.

Và cuối cùng, như Tomek đã chỉ ra, các hàm API phải nằm trong extern C!

Vì vậy:

#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; 
} 
+1

Tôi vừa viết một câu trả lời bao gồm tùy chọn '/ entry' khi tôi nhận thấy câu trả lời tự của bạn có khá nhiều thứ ngoại trừ: 1. Bao gồm' windows.h' sẽ không làm tổn thương kích thước của bạn một chút. Sử dụng '#define WIN32_LEAN_AND_MEAN' và' #define WIN32_EXTRA_LEAN' nếu bạn muốn thực sự chắc chắn. Tiêu đề Win32 không bao gồm tiêu đề CRT, do đó sẽ không có vấn đề ở đây. 2. Bạn có thể đã làm điều này, nhưng vượt qua '/ NODEFAULTLIB' để liên kết và liên kết đến kernel32.lib vv bằng tay. Điều này thực sự nhận được kích thước thực thi kết quả xuống rất nhiều. – rubenvb

2

More đúng tuyên bố điểm vào sẽ là:

int __stdcall wmain(PVOID ThreadParam) 

Nếu không có điểm vào CRT gọi trực tiếp bởi BaseThreadInitThunk. Con trỏ của nó đi đến một cái gì đó, nhưng không phải là argc + argv.

Các vấn đề liên quan