From: Ulrich Eckhardt on
Vincent Fatica wrote:
> On Mon, 07 Sep 2009 09:26:25 +0200, Ulrich Eckhardt
> <eckhardt(a)satorlaser.com> wrote:
>
> |How about this:
> |
> | char simem[sizeof (STARTUPINFO)] = {0};
> | STARTUPINFO si = (STARTUPINFO*)simem;
>
> Did you mean
>
> char simem[sizeof (STARTUPINFO)] = {0};
> STARTUPINFO *psi = (STARTUPINFO*)simem;

Of course, yes.

> That invokes memset, gives the LNK4210 warning, makes a .CRT section, and
> increases the .text segment from 0x9F bytes to 0x9AA bytes (159 to 2474).
>
> SecureZeroMemory and __stosb avoid memset. So does
>
> STARTUPINFO si = {sizeof(si),0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
>
> but that costs about 64 bytes later, moving 0 into each member.

Honestly: I would ignore that and start getting some real work done. ;)

*shrug*

Good luck anyway!

Uli

--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
From: pm on
http://social.msdn.microsoft.com/forums/en-US/Vsexpressvc/thread/a51fe950-cd74-4133-8d84-1bc07b353bc2/
http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/dd0ccf2c-ec28-4b1a-a609-bd962a17febf/

PM-

Vincent Fatica wrote:
> (VC9) I am trying to avoid the runtime library in a tiny app (something I do
> regularly). When I try to zero-fill a STARTUPINFO struct with a for-loop, the
> compiler turns my for-loop into a call to _memset.
>
> ; 13 : STARTUPINFO si;
> ; 14 : si.cb = sizeof(si);
> ; 15 : for (BYTE *p = (BYTE*) &si + sizeof(si.cb); p < (BYTE*) &si +
> sizeof(si); p++)
> ; 16 : *p=0;
>
> push 64 ; 00000040H
> lea edx, DWORD PTR _si$[esp+104]
> push 0
> push edx
> add esi, 2
> mov DWORD PTR _si$[esp+108], 68 ; 00000044H
> call _memset
> add esp, 12 ; 0000000cH
>
> How do I avoid that (elegantly)? Is it some kind of optimization I can simply
> turn off? I can trick the compiler with the likes of
>
> ; 16 : *p = p ? 0 : 1; // in the loop
>
> That avoids the _memset, but seems particularly kludgy.
>
> Thanks.
From: xiaosi on
Mark Lucovsky remarked about BaseProcessStart(PPROCESS_START_ROUTINE lpStartAddress):
"lpStartAddress - Supplies the starting address of the new thread.
The address is logically a procedure that never returns."

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.

00 ntdll!NtTerminateProcess
01 kernel32!_ExitProcess+0x37
02 kernel32!ExitProcess+0x14
03 MSVCR90!__crtExitProcess+0x17 [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0dat.c @ 731]
04 MSVCR90!doexit+0x10a [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0dat.c @ 644]
05 MSVCR90!exit+0x11 [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0dat.c @ 412]
06 winconsol!__tmainCRTStartup+0x125 [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 597]
07 kernel32!BaseProcessStart+0x23

int
__tmainCRTStartup(
void
)
#ifdef WPRFLAG
mainret = wWinMain(
#else /* WPRFLAG */
mainret = WinMain(
#endif /* WPRFLAG */
(HINSTANCE)&__ImageBase,
NULL,
lpszCommandLine,
StartupInfo.dwFlags & STARTF_USESHOWWINDOW
? StartupInfo.wShowWindow
: SW_SHOWDEFAULT
);
#else /* _WINMAIN_ */

#ifdef WPRFLAG
__winitenv = envp;
mainret = wmain(argc, argv, envp);
#else /* WPRFLAG */
__initenv = envp;
mainret = main(argc, argv, envp);
#endif /* WPRFLAG */

#endif /* _WINMAIN_ */

/*
* Note that if the exe is managed app, we don't really need to
* call exit or _c_exit. .cctor should be able to take care of
* this.
*/
if ( !managedapp )
exit(mainret);


"Alex Blekhman" <tkfx.REMOVE(a)yahoo.com> wrote:
> "xiaosi" 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.
>
> This is incorrect. tmainCRTStartup and tWinMainCRTStartup call ExitProcess only if there is an exception thrown from main/WinMain.
> Otherwise, both CRT startup routines just return. kernel32!BaseProcessStart routine calls ExitThread, which in its turn calls
> ExitProcess.
>
> Alex

From: xiaosi on
Yes, the msdn documentation is incorrect about /ENTRY, it had confused me long ago.
EXE ENTRY should be int __cdecl(*)(void), or int __stdcall(*)(void).
DLL ENTRY must be defined as DllMain.

00 hookdll!DllMain [j:\test\hookdll\hookdll.cpp @ 95]
01 hookdll!__DllMainCRTStartup+0x7a [f:\dd\vctools\crt_bld\self_x86\crt\src\crtdll.c @ 546]
02 hookdll!_DllMainCRTStartup+0x1e [f:\dd\vctools\crt_bld\self_x86\crt\src\crtdll.c @ 510]
03 ntdll!LdrpCallInitRoutine+0x14
04 ntdll!LdrpRunInitializeRoutines+0x344
05 ntdll!LdrpInitializeProcess+0x1131
06 ntdll!_LdrpInitialize+0x183
07 ntdll!KiUserApcDispatcher+0x7

BOOL WINAPI
_DllMainCRTStartup(
HANDLE hDllHandle,
DWORD dwReason,
LPVOID lpreserved
)


"Alex Blekhman" <tkfx.REMOVE(a)yahoo.com> wrote:
> I found the requirements here:
>
> "/ENTRY (Entry-Point Symbol)"
> http://msdn.microsoft.com/en-us/library/f9t8842e.aspx
>
> <quote>
> The function must be defined with the __stdcall calling
> convention. The parameters and return value must be defined as
> documented in the Win32 API for WinMain (for an .exe file) or
> DllEntryPoint (for a DLL).
> </quote>
>
> However, after reading your answer I looked into crtexe.c file I
> discovered that CRT startup routines don't respect this
> requirement, exactly as you noticed. Moreover, BaseProcessStart
> routine from kernel32.dll doesn't care neither about parameters
> nor calling convention. The call looks like this:
>
> call dword ptr [ebp+8]
> push eax
> call _ExitThread@4
>
> Where "dword ptr [ebp+8]" is the address of the process entry
> point. The process entry point address is passed as a parameter to
> BaseProcessStart, as well.
>
> So, actually the linker documentation is incorrect and one must
> use int __cdecl(*)(void) function as a custom entry point. It is
> only by sheer luck BaseProcessStart and subsequent code don't
> change anything on stack, so there is no access violation
> exception.
>
> I would be very interested in hearing from MSFT people about the
> issue.
>
> Alex
From: xiaosi on
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.