summaryrefslogtreecommitdiff
path: root/version/version.c
blob: 9fe17c2992f2f8d0b43553033f6f8d391c2fbb19 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/*++

   >>> This code is released to the public domain.  No warranty
       whatsoever is provided.  Use it at your own risk. <<<

Module Name:

    version.c

Abstract:

    Determine the Windows version number running and set the
    errorlevel appropriately.  Intended for use with batch scripts.

Author:

    Scott Gasch ([email protected]) 22 Aug 2002

Revision History:

--*/

#include <stdlib.h>
#include <stdio.h>
#include <windows.h>

//
// This code _should_ run on win9x/ME or any version of NT.  Note: I have
// not personally tested it on 9x/ME though.  It prints out a message on
// stdout about which version of the windows operating system is running
// and sets the errorlevel to one of the values below accordingly.  Might
// be useful in your CMD/BAT script...
//
#define EXIT_WIN95            (1)
#define EXIT_WIN98            (2)
#define EXIT_WINME            (3)
#define EXIT_CONSUMER_OTHER   (4)
#define EXIT_NT351            (5)
#define EXIT_NT3OTHER         (6)
#define EXIT_NT4              (7)
#define EXIT_NT4OTHER         (8)
#define EXIT_WIN2K            (9)
#define EXIT_WINXP            (10)
#define EXIT_WIN_SERVER_2003  (11)
#define EXIT_NT5OTHER         (12)
#define EXIT_VISTA            (13)
#define EXIT_UNKNOWN          (14)

CHAR *g_szWindowsNames[] =
{
    "Not Used",
    "Windows95",
    "Windows98",
    "WindowsME",
    "Unknown Consumer Windows Release",
    "Windows NT",
    "Unknown Windows NT",
    "Windows NT",
    "Unknown Windows NT",
    "Windows 2000",
    "WindowsXP",
    "Windows Server 2003",
    "Unknown Windows NT",
    "Longhorn Prerelease",
    "Unknown Operating System"
};

typedef BOOL (*FUNCTION_PTR)(OSVERSIONINFO *);


BOOL
TryWinNT(DWORD *pdwMajor, DWORD *pdwMinor, DWORD *pdwPlatform)
/*++

Routine description:

    GetVersionEx is not present on downlevel versions of Windows.
    Deal with this by using LoadLibrary/GetProcAddress.

Parameters:

    DWORD *pdwMajor,
    DWORD *pdwMinor,
    DWORD *pdwPlatform

Return value:

    BOOL

--*/
{
    FUNCTION_PTR p;
    BOOL fRet = FALSE;
    HMODULE h = NULL;
    OSVERSIONINFOEXA osvi;

    h = LoadLibraryA("kernel32.dll");
    if (NULL == h)
    {
        fprintf(stderr, "Failed to load kernel32.dll, error=%u.\n",
                GetLastError());
        goto end;
    }

    p = (FUNCTION_PTR)GetProcAddress(h, "GetVersionExA");
    if (NULL == p)
    {
        fprintf(stderr, "GetProcAddress for GetVersionEx failed, error=%u.\n",
                GetLastError());
        goto end;
    }

    ZeroMemory(&osvi, sizeof(osvi));
    osvi.dwOSVersionInfoSize = sizeof(osvi);
    fRet = (*p)((OSVERSIONINFO *)&osvi);
    if (FALSE == fRet)
    {
        fprintf(stderr, "GetVersionEx failed, error=%u.\n", GetLastError());
        goto end;
    }
    *pdwMajor = osvi.dwMajorVersion;
    *pdwMinor = osvi.dwMinorVersion;
    *pdwPlatform = osvi.dwPlatformId;

 end:
    if (NULL != h)
    {
        FreeLibrary(h);
    }

    return(fRet);
}


int __cdecl
main(void)
/*++

Routine description:

    Program entry point.

Parameters:

    void

Return value:

    int __cdecl

--*/
{
    DWORD dwMajor, dwMinor, dwPlatform;
    DWORD dwVersion;
    int iRet = EXIT_UNKNOWN;

    //
    // This call should be available on all versions of Windows
    //
    dwVersion = GetVersion();
    if ((dwVersion & 0x80000000) ||
        (FALSE == TryWinNT(&dwMajor, &dwMinor, &dwPlatform)))
    {
        dwMajor = (DWORD)(LOBYTE(LOWORD(dwVersion)));
        dwMinor = (DWORD)(HIBYTE(LOWORD(dwVersion)));
        dwPlatform = VER_PLATFORM_WIN32_WINDOWS;
    }

    //
    // Parse results
    //
    if (dwPlatform == VER_PLATFORM_WIN32_NT)
    {
        switch(dwMajor)
        {
            case 3:
                iRet = EXIT_NT3OTHER;
                if (51 == dwMinor)
                {
                    iRet = EXIT_NT351;
                }
                goto end;

            case 4:
                iRet = EXIT_NT4OTHER;
                if (0 == dwMinor)
                {
                    iRet = EXIT_NT4;
                }
                goto end;

            case 5:
                iRet = EXIT_NT5OTHER;
                if (0 == dwMinor)
                {
                    iRet = EXIT_WIN2K;
                }
                else if (1 == dwMinor)
                {
                    iRet = EXIT_WINXP;
                }
                else if (2 == dwMinor)
                {
                    iRet = EXIT_WIN_SERVER_2003;
                }
                goto end;

            case 6:
                iRet = EXIT_VISTA;
                goto end;

            default:
                goto end;
        }
    }
    else if (dwPlatform == VER_PLATFORM_WIN32_WINDOWS)
    {
        switch(dwMajor)
        {
            case 4:
                iRet = EXIT_CONSUMER_OTHER;
                if (0 == dwMinor)
                {
                    iRet = EXIT_WIN95;
                }
                else if (10 == dwMinor)
                {
                    iRet = EXIT_WIN98;
                }
                else if (90 == dwMinor)
                {
                    iRet = EXIT_WINME;
                }
                goto end;

            default:
                goto end;
        }
    }

 end:
    printf("%s %u.%u -- errorlevel is %d\n",
           g_szWindowsNames[iRet],
           dwMajor,
           dwMinor,
           iRet);
    exit(iRet);
}