[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Tinycc-devel] __getmainargs compatibility checking success

From: Carlos Montiers
Subject: [Tinycc-devel] __getmainargs compatibility checking success
Date: Sat, 22 Nov 2014 23:41:33 -0300

I modified again the crt1.c for check the success of the function __getmainargs

I investigate this function and I learn some things.

The current protoype is:
int __cdecl __getmainargs (int *pargc, char ***pargv, char ***penvp, int dowildcard, _startupinfo * startinfo)

and is for the version of msvcrt.dll version 7.0 that is present in windows xp

But I found that in the version 6.0 of that dll that is present in windows 98 the prototype was:
void __cdecl __getmainargs (int *pargc, char ***pargv, char ***penvp, int dowildcard, _startupinfo * startinfo)

I get the sources of both from the cd of visual studio 98 and visual studio 2010.

And reading the code and with test I found that the possible result of the function in:
v6.0 are: success or program termination with error code 255 calling function _amsg_exit because not memory available.
v7.0 success (returning 0) or return -1 or program termination with -1 calling function ExitProcess because not memory available. The difference in this last is if the dll was compiled with _SYSCRT definition. I do the test and in windows 7 and 8, and both on no memory available, end the program with -1 (using ExitProcess) but on windows xp, the function return -1.

In the 7.0 version after the error checking, argc and argv are assigned.

Thus, for compatibility with version 6.0 and 7.0 of __getmainargs I check the success of the function, assign NULL to argv, and after the call to the function check if argv is not NULL, because if the function not terminates ending the program, it assign a value to argv. I do test and if the function return -1 (win xp) it not assign a value to argv. Because this I initialize argv to NULL.

Initializing argv to NULL, call __getmainargs and check if argv is NULL is a valid way of check the success of the function, because argv always will point to a address different than 0 (NULL), pointing at least to the the command with which the program is invoked.

I compiled with tcc (without using TRY and the code of SEH) and run succesfully with this crt a program on windows 98.

I use this portion of code for full the heap and cause the failure of __getmainargs :
UINT cant = 1000000;
BYTE *p;
//Alert: fulling heap
while (cant > 1) {
    p = (BYTE *) malloc(cant);
    if (!p) {
        cant /= 2;

And this is the portion of code with the call to __getmainargs and checking the success that works on windows 98 and windows xp and above :

argv = NULL;
__getmainargs(&argc, &argv, &env, 0, &start_info);
// check success comparing if argv now is not NULL
if (! argv)

Also, I found that in the comments of __getmainargs that it left _pgmptr pointing to the program name.
This is because it internally call to GetModuleFileName

Inside the main function you can use this (after success call to __getmainargs).
printf("The full path of the executing program is: %Fs\n", _pgmptr);

This works on both version 6.0 and 7.0 (I tested it on windows 98 and windows 8)

Note the files that have the source code of the functions are:
crtlib.c // __getmainargs
stdargv.c // _setargv (function used by __getmainargs)

With this way you can sure of the success of the function __getmainargs.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]