From: Alex Blekhman on
"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
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
#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
"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
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