Update whitespace and email.
[batch.git] / version / version.c
1 /*++
2
3    >>> This code is released to the public domain.  No warranty
4        whatsoever is provided.  Use it at your own risk. <<<
5
6 Module Name:
7
8     version.c
9
10 Abstract:
11
12     Determine the Windows version number running and set the
13     errorlevel appropriately.  Intended for use with batch scripts.
14
15 Author:
16
17     Scott Gasch ([email protected]) 22 Aug 2002
18
19 Revision History:
20
21 --*/
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <windows.h>
26
27 //
28 // This code _should_ run on win9x/ME or any version of NT.  Note: I have
29 // not personally tested it on 9x/ME though.  It prints out a message on
30 // stdout about which version of the windows operating system is running
31 // and sets the errorlevel to one of the values below accordingly.  Might
32 // be useful in your CMD/BAT script...
33 //
34 #define EXIT_WIN95            (1)
35 #define EXIT_WIN98            (2)
36 #define EXIT_WINME            (3)
37 #define EXIT_CONSUMER_OTHER   (4)
38 #define EXIT_NT351            (5)
39 #define EXIT_NT3OTHER         (6)
40 #define EXIT_NT4              (7)
41 #define EXIT_NT4OTHER         (8)
42 #define EXIT_WIN2K            (9)
43 #define EXIT_WINXP            (10)
44 #define EXIT_WIN_SERVER_2003  (11)
45 #define EXIT_NT5OTHER         (12)
46 #define EXIT_VISTA            (13)
47 #define EXIT_UNKNOWN          (14)
48
49 CHAR *g_szWindowsNames[] =
50 {
51     "Not Used",
52     "Windows95",
53     "Windows98",
54     "WindowsME",
55     "Unknown Consumer Windows Release",
56     "Windows NT",
57     "Unknown Windows NT",
58     "Windows NT",
59     "Unknown Windows NT",
60     "Windows 2000",
61     "WindowsXP",
62     "Windows Server 2003",
63     "Unknown Windows NT",
64     "Longhorn Prerelease",
65     "Unknown Operating System"
66 };
67
68 typedef BOOL (*FUNCTION_PTR)(OSVERSIONINFO *);
69
70
71 BOOL
72 TryWinNT(DWORD *pdwMajor, DWORD *pdwMinor, DWORD *pdwPlatform)
73 /*++
74
75 Routine description:
76
77     GetVersionEx is not present on downlevel versions of Windows.
78     Deal with this by using LoadLibrary/GetProcAddress.
79
80 Parameters:
81
82     DWORD *pdwMajor,
83     DWORD *pdwMinor,
84     DWORD *pdwPlatform
85
86 Return value:
87
88     BOOL
89
90 --*/
91 {
92     FUNCTION_PTR p;
93     BOOL fRet = FALSE;
94     HMODULE h = NULL;
95     OSVERSIONINFOEXA osvi;
96
97     h = LoadLibraryA("kernel32.dll");
98     if (NULL == h)
99     {
100         fprintf(stderr, "Failed to load kernel32.dll, error=%u.\n",
101                 GetLastError());
102         goto end;
103     }
104
105     p = (FUNCTION_PTR)GetProcAddress(h, "GetVersionExA");
106     if (NULL == p)
107     {
108         fprintf(stderr, "GetProcAddress for GetVersionEx failed, error=%u.\n",
109                 GetLastError());
110         goto end;
111     }
112
113     ZeroMemory(&osvi, sizeof(osvi));
114     osvi.dwOSVersionInfoSize = sizeof(osvi);
115     fRet = (*p)((OSVERSIONINFO *)&osvi);
116     if (FALSE == fRet)
117     {
118         fprintf(stderr, "GetVersionEx failed, error=%u.\n", GetLastError());
119         goto end;
120     }
121     *pdwMajor = osvi.dwMajorVersion;
122     *pdwMinor = osvi.dwMinorVersion;
123     *pdwPlatform = osvi.dwPlatformId;
124
125  end:
126     if (NULL != h)
127     {
128         FreeLibrary(h);
129     }
130
131     return(fRet);
132 }
133
134
135 int __cdecl
136 main(void)
137 /*++
138
139 Routine description:
140
141     Program entry point.
142
143 Parameters:
144
145     void
146
147 Return value:
148
149     int __cdecl
150
151 --*/
152 {
153     DWORD dwMajor, dwMinor, dwPlatform;
154     DWORD dwVersion;
155     int iRet = EXIT_UNKNOWN;
156
157     //
158     // This call should be available on all versions of Windows
159     //
160     dwVersion = GetVersion();
161     if ((dwVersion & 0x80000000) ||
162         (FALSE == TryWinNT(&dwMajor, &dwMinor, &dwPlatform)))
163     {
164         dwMajor = (DWORD)(LOBYTE(LOWORD(dwVersion)));
165         dwMinor = (DWORD)(HIBYTE(LOWORD(dwVersion)));
166         dwPlatform = VER_PLATFORM_WIN32_WINDOWS;
167     }
168
169     //
170     // Parse results
171     //
172     if (dwPlatform == VER_PLATFORM_WIN32_NT)
173     {
174         switch(dwMajor)
175         {
176             case 3:
177                 iRet = EXIT_NT3OTHER;
178                 if (51 == dwMinor)
179                 {
180                     iRet = EXIT_NT351;
181                 }
182                 goto end;
183
184             case 4:
185                 iRet = EXIT_NT4OTHER;
186                 if (0 == dwMinor)
187                 {
188                     iRet = EXIT_NT4;
189                 }
190                 goto end;
191
192             case 5:
193                 iRet = EXIT_NT5OTHER;
194                 if (0 == dwMinor)
195                 {
196                     iRet = EXIT_WIN2K;
197                 }
198                 else if (1 == dwMinor)
199                 {
200                     iRet = EXIT_WINXP;
201                 }
202                 else if (2 == dwMinor)
203                 {
204                     iRet = EXIT_WIN_SERVER_2003;
205                 }
206                 goto end;
207
208             case 6:
209                 iRet = EXIT_VISTA;
210                 goto end;
211
212             default:
213                 goto end;
214         }
215     }
216     else if (dwPlatform == VER_PLATFORM_WIN32_WINDOWS)
217     {
218         switch(dwMajor)
219         {
220             case 4:
221                 iRet = EXIT_CONSUMER_OTHER;
222                 if (0 == dwMinor)
223                 {
224                     iRet = EXIT_WIN95;
225                 }
226                 else if (10 == dwMinor)
227                 {
228                     iRet = EXIT_WIN98;
229                 }
230                 else if (90 == dwMinor)
231                 {
232                     iRet = EXIT_WINME;
233                 }
234                 goto end;
235
236             default:
237                 goto end;
238         }
239     }
240
241  end:
242     printf("%s %u.%u -- errorlevel is %d\n",
243            g_szWindowsNames[iRet],
244            dwMajor,
245            dwMinor,
246            iRet);
247     exit(iRet);
248 }
249