From: Alex Blekhman on 8 Sep 2009 11:25 "xiaosi" wrote: > Yes, on my 32bit windows xp sp3, __tmainCRTStartupt > (tmainCRTStartup or tWinMainCRTStartup) never returns to > BaseProcessStart. Without any exception thrown, > __tmainCRTStartup calls exit(), doexit(), __crtExitProcess(), > ExitProcess(), _ExitProcess(), NtTerminateProcess(), and never > returns. Yes, you're right. I overlooked this code. However, even without explicitly calling ExitProcess the BaseProcessStart routine will call it anyway. Here's the stack of CRT-less program after main returns: .... ntdll.dll!_KiFastSystemCall@0() ntdll.dll!_NtTerminateProcess@8() + 0xc bytes kernel32.dll!__ExitProcess@4() + 0x37 bytes kernel32.dll!7c81cb26() kernel32.dll!_ExitThread@4() + 0x63 bytes kernel32.dll!_BaseProcessStart@4() + 0x29 bytes Alex
From: xiaosi on 8 Sep 2009 11:47 int __stdcall mywinmain() is unnecessary, int __cdecl mywinmain() works fine (since it's void parameter). I am accustomed to __stdcall under the influence of the incorrect msdn documentation :-) It's strange that __tmainCRTStartup is not defined explicitly as __cdecl as check_managed_app is: static int __cdecl check_managed_app ( void ) *Purpose: * For an unmanaged app, they call exit and * never return. * *Exit: * Unmanaged app: never return. * *******************************************************************************/ static int __tmainCRTStartup( void ); "Vincent Fatica" <vince(a)blackholespam.net> wrote: > Thanks for the ExitProcess tip. > > __stdcall/WINAPI is not mentioned in crtexe.c. Aren't they all __cdecl? > > static > int > __tmainCRTStartup( > void > ); > > #ifdef _WINMAIN_ > > #ifdef WPRFLAG > int wWinMainCRTStartup( > #else /* WPRFLAG */ > int WinMainCRTStartup( > #endif /* WPRFLAG */ > > #else /* _WINMAIN_ */ > > #ifdef WPRFLAG > int wmainCRTStartup( > #else /* WPRFLAG */ > int mainCRTStartup( > #endif /* WPRFLAG */ > > #endif /* _WINMAIN_ */ > void > ) > { > > On Tue, 8 Sep 2009 13:29:35 +0800, "xiaosi" <xiaosi(a)cn99.com> wrote: > > |Besides call convention, ExitProcess should be used instead of return, because both tmainCRTStartup and tWinMainCRTStartup call > |kernel32!ExitProcess(status) after tmain or tWinMain return status. > | > |If you use Common Dialog Box in your app, and return (instead of ExitProcess) to exit app, the process will not exit (the thread > of > |Common Dialog Box is still existing). > | > |#pragma comment(linker, "/subsystem:windows") > |#pragma comment(linker, "/entry:mywinmain") > |int __stdcall mywinmain() { > | .... > | ExitProcess(msg.wParam); > |} > | > |#pragma comment(linker, "/subsystem:console") > |#pragma comment(linker, "/entry:mymain") > |int __cdecl mymain() { > | .... > | ExitProcess(status); > |}
From: xiaosi on 8 Sep 2009 12:05 #pragma comment(linker, "/nodefaultlib:libcmt.lib") is enough #pragma comment(linker, "/nodefaultlib") will prevent memset to link to ntdll.lib. "xiaosi" <xiaosi(a)cn99.com> wrote: > When I write: > #pragma comment(lib, "F:\\WINDDK\\3790.1830\\lib\\wxp\\i386\\ntdll.lib") > VC always import memset from ntdll.lib instead of CRT lib. > > To ensure not to import anything from CRT lib, I write: > #pragma comment(linker, "/nodefaultlib") > But this need to write every lib you will use: > #pragma comment(lib, "kernel32") > #pragma comment(lib, "user32") > #pragma comment(lib, "gdi32") > #pragma comment(lib, "comctl32") > > "Vincent Fatica" <vince(a)blackholespam.net> wrote: >> >> How do I ensure my app get them from ntdll.dll and not try to get them from the >> CRT lib? >> >> On Tue, 8 Sep 2009 13:32:29 +0800, "xiaosi" <xiaosi(a)cn99.com> wrote: >> >> |One day I dumpbin /headers /exports ntdll.dll > exports_ntdll.txt, and find ntdll.dll has many "built-in" crt functions. When >> system >> |loads an app, it always firstly maps ntdll.dll to the app's process. This means every app has these "built-in" crt functions, so >> why >> |bother to import these functions from the crt lib (except using inline for speed). wcstoul/wcstol/strtoul/strtol are also >> "built-in" >> |in ntdll.dll.
From: xiaosi on 8 Sep 2009 13:21 "ExitThread Function: If the thread is the last thread in the process when this function is called, the thread's process is also terminated."[1] windows xp sp3: 00 ntdll!NtTerminateProcess 01 kernel32!_ExitProcess+0x37 02 kernel32!ExitProcess+0x14 03 kernel32!ExitThread+0x92 04 kernel32!BaseProcessStart+0x28 When I open the GetOpenFileName Dialog Box[2], the process adds three threads (one ntdll.dll!RtlpTimerThread + two ntdll.dll!RtlpWorkerThread). When I close the GetOpenFileName Dialog Box, the nocrt.exe!main thread exits, but the other three threads remain. After several minutes, the two ntdll.dll!RtlpWorkerThread exit but the ntdll.dll!RtlpTimerThread remains. The process is not terminated! [1] http://msdn.microsoft.com/en-us/library/ms682659.aspx [2] #pragma comment(linker, "/entry:main") #pragma comment(linker, "/subsystem:console") #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df'\"") #pragma comment(lib, "kernel32") #pragma comment(lib, "comdlg32") #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <commdlg.h> //GetOpenFileName #include <intrin.h> //__stosd int __cdecl main() { OPENFILENAME op; char file[MAX_PATH*2]; __stosd((unsigned long *)&op, 0, sizeof(op)/4); // 88/4=22 op.lStructSize = sizeof(op); op.lpstrFile = file; op.nMaxFile = sizeof(file); GetOpenFileName(&op); return 0; } "Alex Blekhman" <tkfx.REMOVE(a)yahoo.com> wrote: > "xiaosi" wrote: >> Yes, on my 32bit windows xp sp3, __tmainCRTStartupt >> (tmainCRTStartup or tWinMainCRTStartup) never returns to >> BaseProcessStart. Without any exception thrown, >> __tmainCRTStartup calls exit(), doexit(), __crtExitProcess(), >> ExitProcess(), _ExitProcess(), NtTerminateProcess(), and never >> returns. > > Yes, you're right. I overlooked this code. However, even without > explicitly calling ExitProcess the BaseProcessStart routine will > call it anyway. Here's the stack of CRT-less program after main > returns: > > ... > ntdll.dll!_KiFastSystemCall@0() > ntdll.dll!_NtTerminateProcess@8() + 0xc bytes > kernel32.dll!__ExitProcess@4() + 0x37 bytes > kernel32.dll!7c81cb26() > kernel32.dll!_ExitThread@4() + 0x63 bytes > kernel32.dll!_BaseProcessStart@4() + 0x29 bytes > > > Alex
From: Vincent Fatica on 8 Sep 2009 14:15
On Tue, 8 Sep 2009 23:06:07 +0800, "xiaosi" <xiaosi(a)cn99.com> wrote: |When I write: |#pragma comment(lib, "F:\\WINDDK\\3790.1830\\lib\\wxp\\i386\\ntdll.lib") |VC always import memset from ntdll.lib instead of CRT lib. | |To ensure not to import anything from CRT lib, I write: |#pragma comment(linker, "/nodefaultlib") |But this need to write every lib you will use: |#pragma comment(lib, "kernel32") |#pragma comment(lib, "user32") |#pragma comment(lib, "gdi32") |#pragma comment(lib, "comctl32") I downloaded the WDK so I suppose after installing it I'll have an ntdll.h and ntdll.lib (right?). Can't I just ignore, specifically, libcmt.lib? -- - Vince |