Figure 1 TEST.MAP from Visual C++ 4.1
0001:00000000 _main 00401000 f test.obj
0001:00000010 _mainCRTStartup 00401010 f LIBC:crt0.obj
0001:00000120 __amsg_exit 00401120 f LIBC:crt0.obj
0001:00000150 __cinit 00401150 f LIBC:crt0dat.obj
0001:00000180 _exit 00401180 f LIBC:crt0dat.obj
0001:000001a0 __exit 004011a0 f LIBC:crt0dat.obj
0001:00000290 __global_unwind2 00401290 f LIBC:exsup.obj
0001:000002d2 __local_unwind2 004012d2 f LIBC:exsup.obj
0001:0000032a __NLG_Return2 0040132a LIBC:exsup.obj
0001:0000033a __abnormal_termination 0040133a f LIBC:exsup.obj
0001:0000035d __NLG_Notify1 0040135d f LIBC:exsup.obj
0001:00000366 __NLG_Notify 00401366 f LIBC:exsup.obj
0001:00000379 __NLG_Dispatch 00401379 LIBC:exsup.obj
0001:00000380 __XcptFilter 00401380 f LIBC:winxfltr.obj
0001:00000510 __setenvp 00401510 f LIBC:stdenvp.obj
0001:000005f0 __setargv 004015f0 f LIBC:stdargv.obj
0001:00000870 ___crtGetEnvironmentStringsA 00401870 f LIBC:aw_env.obj
0001:00000a10 __setmbcp 00401a10 f LIBC:mbctype.obj
0001:00000cd0 ___initmbctable 00401cd0 f LIBC:mbctype.obj
0001:00000ce0 __ioinit 00401ce0 f LIBC:ioinit.obj
0001:00000ec0 __heap_init 00401ec0 f LIBC:heapinit.obj
0001:00000ee0 __except_handler3 00401ee0 f LIBC:exsup3.obj
0001:00000f9d __seh_longjmp_unwind@4 00401f9d f LIBC:exsup3.obj
0001:00000fc0 __FF_MSGBANNER 00401fc0 f LIBC:crt0msg.obj
0001:00001000 __NMSG_WRITE 00402000 f LIBC:crt0msg.obj
0001:000011f0 _free 004021f0 f LIBC:free.obj
0001:00001210 _malloc 00402210 f LIBC:malloc.obj
0001:00001230 __nh_malloc 00402230 f LIBC:malloc.obj
0001:00001270 __heap_alloc 00402270 f LIBC:malloc.obj
0001:00001290 ___crtMessageBoxA 00402290 f LIBC:crtmbox.obj
0001:00001330 _strncpy 00402330 f LIBC:strncpy.obj
0001:00001430 __callnewh 00402430 f LIBC:handler.obj
0001:00001450 _RtlUnwind@16 00402450 f kernel32:KERNEL32.dll
Figure 2 TEST.MAP from Borland C++ 5.0
Address Publics by Value
0001:0000007C _main
0001:00000084 _memchr
0001:000000A4 _memcpy
0001:000000C8 _memmove
0001:00000114 _memset
0001:00000144 _strcmp
0001:00000170 _strlen
0001:0000018C _memcmp
0001:000001D0 _strrchr
0001:00000BBE _ThrowException(...
0001:00000D57 _CatchCleanup()
0001:0000117E __Local_unwind
0001:000011FB __ExceptionHandler
0001:00001B81 __CurrExcContext
0001:00001F72 __tpdsc__[typeinfo*]
0001:00001F89 __tpdsc__[Bad_typeid]
0001:00001FA5 __tpdsc__[Bad_cast]
0001:00001FC1 __tpdsc__[typeinfo]
0001:0000200C @__InitExceptBlock
0001:00002077 ___call_terminate
0001:0000215B ___call_unexpected
0001:000021CF __GetPolymorphicDTC(void*,unsigned int)
0001:000021EE __ExceptInit
0001:000022D0 __GetExceptDLLinfoInternal
0001:0000230C __lockDebuggerData()
0001:00002334 __unlockDebuggerData()
0001:00002340 ___DefHandler
0001:00002460 __InitDefaultHander
0001:0000247A ___doGlobalUnwind
0001:0000248F invokeHnd()
0001:00002498 __SetExceptionHandler
0001:000024AD __UnsetExceptionHandler
0001:000024E0 _flushall
0001:000024E8 __allocbuf
0001:00002568 _fflush
0001:000025F0 __flushout
0001:00002650 __initfmode
0001:00002660 ___fputn
0001:00002734 _fputs
0001:00002774 _fputc
0001:0000290C _sprintf
0001:0000298C __init_streams
0001:00002B1C ___vprinter
0001:0000317C __xfflush
0001:000031BC __flushall
0001:000031F4 __umask
0001:000032C4 ___write
0001:000033A4 __get_handle
0001:000033E4 __dup_handle
0001:00003504 __init_handles
0001:00003648 ___IOerror
0001:0000368C ___DOSerror
0001:000036AC ___NTerror
0001:000036C0 __rtl_write
0001:00003724 ___close
0001:00003770 ___isatty
0001:000037A0 ___isatty_osfhandle
0001:000037B8 ___lseek
0001:00003830 ___open
0001:00003A28 __clear87
0001:00003A3C __control87
0001:00003A64 ___realcvt
0001:00003A6A ___nextreal
0001:00003A70 __scantod
0001:00003A76 __scanrslt
0001:00003A7C __fpreset
0001:00003AAC ___longtoa
0001:00003B20 ___utoa
0001:00003B3C __matherr
0001:00003B68 __matherrl
0001:00003B98 __initmatherr
0001:000041B8 _free
0001:000042C0 ___org_malloc
0001:000042C0 _malloc
0001:00004754 _realloc
0001:000047EC operator delete(void*)
0001:000047FC operator delete[](void*)
0001:0000480C __virt_reserve
0001:00004878 __virt_commit
0001:000048CC __virt_decommit
0001:000048F0 __virt_release
0001:00004978 __ErrorMessage
0001:00004A68 __ErrorExit
0001:00004AE0 __ErrorMessageHelper
0001:00004B90 __abort
0001:00004BA4 _abort
0001:00004C10 _exit
0001:00004C28 __exit
0001:00004C60 __initwild
0001:00004E5C __addarg
0001:00005180 _raise
0001:000051F8 __create_shmem
0001:00005200 __init_exit_proc
0001:000052AC __startup
0001:00005414 __cleanup
0001:0000548C __terminate
0001:000054A0 _getdate
Figure 3 CRT0TWIN.C
//==========================================
// TINYCRT - Matt Pietrek 1996
// Microsoft Systems Journal, October 1996
// FILE: CRT0TWIN.C
//==========================================
#include <windows.h>
#ifndef __BORLANDC__
// Force the linker to include KERNEL32.LIB
#pragma comment(linker, "/defaultlib:kernel32.lib")
#endif
//
// Modified version of the Visual C++ 4.1 startup code. Simplified to
// make it easier to read. Only supports ANSI programs.
//
void __cdecl WinMainCRTStartup( void )
{
int mainret;
char *lpszCommandLine;
STARTUPINFO StartupInfo;
lpszCommandLine = GetCommandLine();
// Skip past program name (first token in command line).
if ( *lpszCommandLine == '"' ) //Check for and handle quoted program name
{
// Scan, and skip over, subsequent characters until another
// double-quote or a null is encountered
while( *lpszCommandLine && (*lpszCommandLine != '"') )
lpszCommandLine++;
// If we stopped on a double-quote (usual case), skip over it.
if ( *lpszCommandLine == '"' )
lpszCommandLine++;
}
else // First token wasn't a quote
{
while ( *lpszCommandLine > ' ' )
lpszCommandLine++;
}
// Skip past any white space preceeding the second token.
while ( *lpszCommandLine && (*lpszCommandLine <= ' ') )
lpszCommandLine++;
StartupInfo.dwFlags = 0;
GetStartupInfo( &StartupInfo );
mainret = WinMain( GetModuleHandle(NULL),
NULL,
lpszCommandLine,
StartupInfo.dwFlags & STARTF_USESHOWWINDOW
? StartupInfo.wShowWindow : SW_SHOWDEFAULT );
ExitProcess(mainret);
}
Figure 4 CRT0TCON.C
//==========================================
// TINYCRT - Matt Pietrek 1996
// Microsoft Systems Journal, October 1996
// FILE: CRT0TCON.C
//==========================================
#include <windows.h>
#include "argcargv.h"
#ifndef __BORLANDC__
// Force the linker to include KERNEL32.LIB
#pragma comment(linker, "/defaultlib:kernel32.lib")
#endif
int __cdecl main(int, char **, char **); // In user supplied code
void __cdecl mainCRTStartup( void )
{
int mainret, argc;
argc = _ConvertCommandLineToArgcArgv( );
mainret = main( argc, _ppszArgv, 0 );
ExitProcess(mainret);
}
Figure 5 ARGCARGV.C
//==========================================
// TINYCRT - Matt Pietrek 1996
// Microsoft Systems Journal, October 1996
// FILE: ARGCARGV.C
//==========================================
#include <windows.h>
#include "argcargv.h"
#define _MAX_CMD_LINE_ARGS 128
char * _ppszArgv[_MAX_CMD_LINE_ARGS+1];
int __cdecl _ConvertCommandLineToArgcArgv( void )
{
int cbCmdLine;
int argc;
PSTR pszSysCmdLine, pszCmdLine;
// Set to no argv elements, in case we have to bail out
_ppszArgv[0] = 0;
// First get a pointer to the system's version of the command line, and
// figure out how long it is.
pszSysCmdLine = GetCommandLine();
cbCmdLine = lstrlen( pszSysCmdLine );
// Allocate memory to store a copy of the command line. We'll modify
// this copy, rather than the original command line. Yes, this memory
// currently doesn't explicitly get freed, but it goes away when the
// process terminates.
pszCmdLine = HeapAlloc( GetProcessHeap(), 0, cbCmdLine+1 );
if ( !pszCmdLine )
return 0;
// Copy the system version of the command line into our copy
lstrcpy( pszCmdLine, pszSysCmdLine );
if ( '"' == *pszCmdLine ) // If command line starts with a quote ("),
{ // it's a quoted filename. Skip to next quote.
pszCmdLine++;
_ppszArgv[0] = pszCmdLine; // argv[0] == executable name
while ( *pszCmdLine && (*pszCmdLine != '"') )
pszCmdLine++;
if ( *pszCmdLine ) // Did we see a non-NULL ending?
*pszCmdLine++ = 0; // Null terminate and advance to next char
else
return 0; // Oops! We didn't see the end quote
}
else // A regular (non-quoted) filename
{
_ppszArgv[0] = pszCmdLine; // argv[0] == executable name
while ( *pszCmdLine && (' ' != *pszCmdLine) && ('\t' != *pszCmdLine) )
pszCmdLine++;
if ( *pszCmdLine )
*pszCmdLine++ = 0; // Null terminate and advance to next char
}
// Done processing argv[0] (i.e., the executable name). Now do th
// actual arguments
argc = 1;
while ( 1 )
{
// Skip over any whitespace
while ( *pszCmdLine && (' ' == *pszCmdLine) || ('\t' == *pszCmdLine) )
pszCmdLine++;
if ( 0 == *pszCmdLine ) // End of command line???
return argc;
if ( '"' == *pszCmdLine ) // Argument starting with a quote???
{
pszCmdLine++; // Advance past quote character
_ppszArgv[ argc++ ] = pszCmdLine;
_ppszArgv[ argc ] = 0;
// Scan to end quote, or NULL terminator
while ( *pszCmdLine && (*pszCmdLine != '"') )
pszCmdLine++;
if ( 0 == *pszCmdLine )
return argc;
if ( *pszCmdLine )
*pszCmdLine++ = 0; // Null terminate and advance to next char
}
else // Non-quoted argument
{
_ppszArgv[ argc++ ] = pszCmdLine;
_ppszArgv[ argc ] = 0;
// Skip till whitespace or NULL terminator
while ( *pszCmdLine && (' '!=*pszCmdLine) && ('\t'!=*pszCmdLine) )
pszCmdLine++;
if ( 0 == *pszCmdLine )
return argc;
if ( *pszCmdLine )
*pszCmdLine++ = 0; // Null terminate and advance to next char
}
if ( argc >= (_MAX_CMD_LINE_ARGS) )
return argc;
}
}
Figure 6 PRINTF.C
#include <windows.h>
#include <stdio.h>
#include <stdarg.h>
#ifndef __BORLANDC__
// Force the linker to include USER32.LIB
#pragma comment(linker, "/defaultlib:user32.lib")
#endif
int __cdecl printf(const char * format, ...)
{
char szBuff[1024];
int retValue;
DWORD cbWritten;
va_list argptr;
va_start( argptr, format );
retValue = wvsprintf( szBuff, format, argptr );
va_end( argptr );
WriteFile( GetStdHandle(STD_OUTPUT_HANDLE), szBuff, retValue,
&cbWritten, 0 );
return retValue;
}
Figure 7 ISCTYPE.C
// 1996 - John Robbins, with Matt Pietrek
#include <ctype.h>
int __cdecl _isctype ( int c , int mask )
{
/* c valid between -1 and 255 */
if (((unsigned)(c + 1)) <= 256)
{
return ( _pctype[c] & mask ) ;
}
else
return 0;
}