1 /* $Id: sys.c,v 1.37 2020-11-02 23:20:52 phil Exp $ */
2
3 /* support for HOST() on Win32 pb 12/22/97 */
4
5 #ifdef HAVE_CONFIG_H
6 #include "config.h"
7 #endif /* HAVE_CONFIG_H defined */
8
9 #include <windows.h>
10 #include <stdio.h>
11
12 #include "h.h"
13 #include "snotypes.h"
14 #include "lib.h"
15 #include "str.h"
16
17 void
hwname(char * cp)18 hwname(char *cp) {
19 char *hw;
20 SYSTEM_INFO si;
21
22 GetSystemInfo(&si); /* no return value */
23
24 switch (si.wProcessorArchitecture) {
25 case PROCESSOR_ARCHITECTURE_INTEL:
26 /*
27 * wProcessorLevel, not used on Windows 95.
28 * dwProcessorType contains mnemonic values, but is obsolete on WinNT!
29 */
30 hw = "x86";
31 break;
32
33 case PROCESSOR_ARCHITECTURE_MIPS:
34 hw = "mips";
35 break;
36
37 case PROCESSOR_ARCHITECTURE_ALPHA:
38 hw = "alpha";
39 break;
40
41 case PROCESSOR_ARCHITECTURE_PPC:
42 hw = "ppc";
43 break;
44
45 #ifdef PROCESSOR_ARCHITECTURE_IA64
46 case PROCESSOR_ARCHITECTURE_IA64:
47 hw = "ia64";
48 break;
49 #endif
50
51 #ifdef PROCESSOR_ARCHITECTURE_AMD64
52 case PROCESSOR_ARCHITECTURE_AMD64:
53 hw = "amd64";
54 break;
55 #endif
56
57 #ifdef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
58 case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
59 hw = "WOW64";
60 break;
61 #endif
62
63 #ifdef PROCESSOR_ARCHITECTURE_ARM
64 case PROCESSOR_ARCHITECTURE_ARM:
65 hw = "arm";
66 break;
67 #endif
68
69 default:
70 sprintf(cp, "arch#%d", si.wProcessorArchitecture);
71 return;
72 }
73 strcpy(cp, hw);
74 }
75
76 void
osname(char * cp)77 osname(char *cp) {
78 char osname[32], *os;
79 OSVERSIONINFOEXA osv;
80 int server = 0;
81 int build = 0;
82 int vnum = 0;
83
84 ZeroMemory(&osv, sizeof(osv));
85 osv.dwOSVersionInfoSize = sizeof(osv);
86 /*
87 * https://docs.microsoft.com/en-us/windows/win32/sysinfo/targeting-your-application-at-windows-8-1
88 * 5/31/2018:
89 * In Windows 8.1 and Windows 10, the GetVersion and GetVersionEx
90 * functions have been deprecated. In Windows 10, the
91 * VerifyVersionInfo function has also been deprecated. While you
92 * can still call the deprecated functions, if your application
93 * does not specifically target Windows 8.1 or Windows 10, the
94 * functions will return the Windows 8 version (6.2).
95 */
96
97 /*
98 * PLB 11/2/2020:
99 * Aparently there's an undocumented interface in NTDLL that's used my the MSVCRT:
100 * extern VOID WINAPI RtlGetNtVersionNumbers(LPDWORD pMajor, LPDWORD pMinor, LPDWORD pBuild);
101 *
102 * Also "the kernel-mode equivalent of the user-mode GetVersionEx function in the Windows SDK":
103 * RtlGetVersion
104 */
105
106 /* uncharmingly, GetVersionExA wants a OSVERSIONINFOA
107 * but OSVERSIONINFOEXA doesn't start with one!!
108 */
109 if (!GetVersionExA((LPOSVERSIONINFO)&osv)) {
110 strcpy(cp, "Win????");
111 return;
112 }
113 #ifdef DEBUG_SYS
114 printf("plat %ld %ld.%ld.%ld ptype %d\n",
115 osv.dwPlatformId,
116 osv.dwMajorVersion,
117 osv.dwMinorVersion,
118 osv.dwBuildNumber,
119 osv.wProductType);
120 #define HERE printf("line %d\n", __LINE__)
121 #else
122 #define HERE (void)0
123 #endif
124 build = osv.dwBuildNumber;
125 server = (osv.wProductType != VER_NT_WORKSTATION);
126 switch (osv.dwPlatformId) {
127 case VER_PLATFORM_WIN32s:
128 os = "Win32s";
129 break;
130
131 case VER_PLATFORM_WIN32_WINDOWS:
132 /*
133 * If the dwPlatformId member of that structure is
134 * VER_PLATFORM_WIN32_WINDOWS, and the low word of the
135 * dwBuildNumber member is "1111," the system is running
136 * Windows 95 OSR 2. For Windows 95 and Windows 95 OSR 2, the
137 * dwMajorVersion element returns "4" and dwMinorVersion
138 * returns "0." Future versions or OSRs of Windows 95 will
139 * have higher build numbers. They may also have higher
140 * major/minor version numbers.
141 */
142 os = "Win??";
143 build &= 0xffff;
144 if (osv.dwMajorVersion == 4) {
145 switch (osv.dwMinorVersion) {
146 case 0:
147 os = "Win95";
148 if (osv.szCSDVersion[1] == 'A' ||
149 osv.szCSDVersion[1] == 'B') {
150 os = "Win95 OSR2";
151 osv.szCSDVersion[0] = '\0';
152 }
153 break;
154 case 10:
155 os = "Win98";
156 if (osv.szCSDVersion[1] == 'A') {
157 os = "Win98SE";
158 osv.szCSDVersion[0] = '\0';
159 }
160 break;
161 case 90:
162 os = "WinME";
163 break;
164 default:
165 vnum = 1;
166 HERE;
167 break;
168 }
169 }
170 break;
171
172 case VER_PLATFORM_WIN32_NT:
173 /* also osv.wProductType, wSuiteMask */
174 os = "WinNT";
175 switch (osv.dwMajorVersion) {
176 case 5:
177 switch (osv.dwMinorVersion) {
178 case 0:
179 os = "Win2K";
180 break;
181 case 1:
182 os = "WinXP";
183 break;
184 case 2:
185 os = "WinServer2003";
186 break;
187 default:
188 vnum = 1;
189 HERE;
190 break;
191 } // 5
192 break;
193
194 case 6: /* "Longhorn" family */
195 switch (osv.dwMinorVersion) {
196 case 0:
197 if (server)
198 os = "WinServer2008";
199 else
200 os = "WinVista";
201 break;
202 case 1:
203 if (server)
204 os = "WinServer2008R2";
205 else
206 os = "Win7";
207 break;
208 case 2:
209 if (server)
210 os = "WinServer2012";
211 else
212 os = "Win8";
213 break;
214 case 3: /* not returned unless manifested (see above) */
215 if (server)
216 os = "WinServer2012R2";
217 else
218 os = "Win8.1";
219 break;
220 case 4: /* prior to build 9926 (only if manifested) */
221 if (server)
222 os = "WinServer2016";
223 else
224 os = "Win10";
225 break;
226 default:
227 vnum = 1;
228 HERE;
229 break;
230 } // 6
231 break;
232
233 case 10: /* not returned unless binary manifested for Win10 (else 6.2) */
234 switch (osv.dwMinorVersion) {
235 case 0:
236 if (server)
237 os = "WinServer2016"; /* 2019 if build >=1809? */
238 else
239 os = "Win10";
240 break;
241 /*
242 * anything added here will not be seen unless snobol4.exe.manifest
243 * updated with guid of new OS
244 */
245 default:
246 vnum = 1;
247 HERE;
248 break;
249 } // 10
250 break;
251
252 default:
253 vnum = 1;
254 HERE;
255 break;
256 } // dwMajorVersion
257 break;
258
259 default:
260 sprintf(osname, "Win#%d", (int)osv.dwPlatformId);
261 os = osname;
262 vnum = 1;
263 HERE;
264 break;
265 } // dwPlatformId
266
267 if (vnum) {
268 sprintf(cp, "%s %d.%d", os, (int)osv.dwMajorVersion, (int)osv.dwMinorVersion);
269 if (build) {
270 cp += strlen(cp);
271 sprintf(cp, ".%d", build);
272 }
273 if (server)
274 strcat(cp, " server");
275 }
276 else
277 strcpy(cp, os);
278
279 cp += strlen(cp);
280
281 /*
282 * szCSDVersion:
283 *
284 * Windows NT: Contains a null-terminated string, such as "Service
285 * Pack 3", that indicates the latest Service Pack installed on
286 * the system. If no Service Pack has been installed, the string
287 * is empty.
288 *
289 * Windows 95: Contains a null-terminated string that provides
290 * arbitrary additional information about the operating system.
291 */
292 if (osv.szCSDVersion[0]) {
293 char *tp;
294
295 /* strip trailing spaces, if any */
296 tp = osv.szCSDVersion + strlen(osv.szCSDVersion);
297 while (tp > osv.szCSDVersion && tp[-1] == ' ')
298 tp--;
299 *tp = '\0';
300
301 /* strip leading spaces, if any */
302 tp = osv.szCSDVersion;
303 while (*tp && *tp == ' ')
304 tp++;
305
306 /* ignore if empty */
307 if (*tp) {
308 *cp++ = ' ';
309 while ((*cp++ = *tp++))
310 ;
311 }
312 }
313 }
314