From: hpv@kelvin.uio.no (Hans Peter Verne)
Subject: Detecting Windows, the solution !
Organization: University of Oslo, Norway
Date: Wed, 18 Nov 1992 17:05:39 GMT


< this is a borrowed account, short messages may be routed to Tormod >

Follow UP (from Tormod): Detecting Windows, and in which mode !

The section below are MY comments on all the suggestions I got...
And finally a short program which works for me... I'm not saying
that I'm doing it the correct way but it works. From all the responses
I got it is clear to see that there is no 'proper' way. Couldn't 
Microsoft have created ONE simple interrupt, which returns windows
version, modifies AX on return and which mode we're in ?

I want to thank everyone who replied...( quite a few actually )
( To save netspace I'm not quoting, forgive me... ). 
Please no flames. This may not be how you would do it !!

And so for the different propositions:

'Peeking' the interrupt table is ambiguous, the table does not necessary 
contain 00 in the offset if an interrupt handler is not installed. In fact
it does not contain 0 at all but points to a default handler which just
returns. All registers are generally the same as when we called it. 

Walking the MCB chain works, but requires the use of UNDOCUMENTED DOS
which just happens to change between DOS versions.

2F-1600 : Ambiguous test, there is no way to determine if the interrupt was
handled correctly. If there is no 2F1600 handler installed AX will be
1600 on return. The test for enhanced mode when AL == 00 will
always be true. Therefore in standard DOS, Windows is apparently 
in enhanced mode ! I.e. before using this test we have to determine 
if windows is running. ( That's what Microsoft does... )

2F-160A : Found this one by tracing win.com. Works like this..
int 2F   160A  ************* only under windows 3.1 *************
  Return  
        AX = 0
        BX = 30A          isn't this the timestamp on Windows 3.0 files ?
        CX = 003          Enhanced mode
        CX = 002          Standard mode
  Microsoft uses this in win.com in the following order:
  2F-160A -> 2F-1600 -> 2F-4680
An excellent interrupt since it sets AX to zero if a handler is present.
Only present in 3.1 though.

2F-4680 : also ambiguous if it's not established if Windows is running or 
not, since if AX is non zero it's in enhanced mode ( same problem as 
described in 2F1600 ). However if Windows is running, it's good. Since
we will find out whether we're in enhanced mode or not. Drawback
is that it's not officially documented. Microsoft uses it, though..

"windir" variable (lowercase) is not official either ( I read somewhere.. )
but it works extremely well. It can be used to determine if Windows is 
there at all. Then you can use 2F-4680.

/* and here is my choice...  Works under 3.0 and 3.1 */

#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()   
{
    union REGS reg;
    char *pEnvStr;

    if ((pEnvStr = (getenv("windir"))) != NULL)
      printf("found 'windir' ( Windows is running )\n");
    else
    {
      printf("Windows is not active\n");
      return 0;
    }
    
    /* this test can only be run after we've verified that windows is active */
    reg.x.ax = 0x4680;  
    int86(0x2f, &reg, &reg);
    if ( reg.x.ax == 0 )   
    {
      printf("Real mode or standard is here....\n");
      return 0;
    }
    printf("ENHANCED...\n");
    return 0;
}