Large-scale renaming of all Win32 functions and types to use the
[wine] / misc / version.c
1 /*
2  * Windows and DOS version functions
3  *
4  * Copyright 1997 Alexandre Julliard
5  * Copyright 1997 Marcus Meissner
6  * Copyright 1998 Patrik Stridvall
7  * Copyright 1998 Andreas Mohr
8  */
9
10 #include <string.h>
11 #include <stdlib.h>
12 #include "winbase.h"
13 #include "winuser.h"
14 #include "wine/winbase16.h"
15 #include "process.h"
16 #include "options.h"
17 #include "debug.h"
18 #include "neexe.h"
19 #include "winversion.h"
20
21 typedef struct
22 {
23     LONG             getVersion16; 
24     LONG             getVersion32;
25     OSVERSIONINFOA getVersionEx;
26 } VERSION_DATA;
27
28
29 /* FIXME: compare values below with original and fix */
30 static VERSION_DATA VersionData[NB_WINDOWS_VERSIONS] =
31 {
32     /* WIN31 */
33     {
34         MAKELONG( 0x0a03, 0x0616 ), /* DOS 6.22 */
35         MAKELONG( 0x0a03, 0x8000 ),
36         {
37             sizeof(OSVERSIONINFOA), 3, 10, 0,
38             VER_PLATFORM_WIN32s, "Win32s 1.3" 
39         }
40     },
41     /* WIN95 */
42     {
43         0x07005F03,
44         0xC0000004,
45         {
46             sizeof(OSVERSIONINFOA), 4, 0, 0x40003B6,
47             VER_PLATFORM_WIN32_WINDOWS, "Win95"
48         }
49     },
50     /* NT351 */
51     {
52         0x05000A03,
53         0x04213303,
54         {
55             sizeof(OSVERSIONINFOA), 3, 51, 0x421,
56             VER_PLATFORM_WIN32_NT, "Service Pack 2"
57         }
58     },
59     /* NT40 */
60     {
61         0x05000A03,
62         0x05650004,
63         {
64             sizeof(OSVERSIONINFOA), 4, 0, 0x565,
65             VER_PLATFORM_WIN32_NT, "Service Pack 3"
66         }
67     }
68 };
69
70 static const char *WinVersionNames[NB_WINDOWS_VERSIONS] =
71 {
72     "win31",
73     "win95",
74     "nt351",
75     "nt40"
76 };
77
78 /* the current version has not been autodetected but forced via cmdline */
79 static BOOL versionForced = FALSE;
80 static WINDOWS_VERSION defaultWinVersion = WIN31;
81
82
83 /**********************************************************************
84  *         VERSION_ParseWinVersion
85  */
86 void VERSION_ParseWinVersion( const char *arg )
87 {
88     int i;
89     for (i = 0; i < NB_WINDOWS_VERSIONS; i++)
90     {
91         if (!strcmp( WinVersionNames[i], arg ))
92         {
93             defaultWinVersion = (WINDOWS_VERSION)i;
94             versionForced = TRUE;
95             return;
96         }
97     }
98     MSG("Invalid winver value '%s' specified.\n", arg );
99     MSG("Valid versions are:" );
100     for (i = 0; i < NB_WINDOWS_VERSIONS; i++)
101         MSG(" '%s'%c", WinVersionNames[i],
102             (i == NB_WINDOWS_VERSIONS - 1) ? '\n' : ',' );
103 }
104
105
106 /**********************************************************************
107  *         VERSION_ParseDosVersion
108  */
109 void VERSION_ParseDosVersion( const char *arg )
110 {
111     int hi, lo;
112     if (sscanf( arg, "%d.%d", &hi, &lo ) == 2)
113     {
114         VersionData[WIN31].getVersion16 =
115             MAKELONG(LOWORD(VersionData[WIN31].getVersion16),
116                      (hi<<8) + lo);
117     }
118     else
119         fprintf( stderr, "-dosver: Wrong version format. Use \"-dosver x.xx\"\n");
120 }
121
122
123 /**********************************************************************
124  *         VERSION_GetVersion
125  */
126 WINDOWS_VERSION VERSION_GetVersion(void)
127 {
128     PIMAGE_NT_HEADERS peheader; 
129
130     if (versionForced) /* user has overridden any sensible checks */
131         return defaultWinVersion;
132     if (!PROCESS_Current()->exe_modref)
133     {
134         /* HACK: if we have loaded a PE image into this address space,
135          * we are probably using thunks, so Win95 is our best bet
136          */
137         if (PROCESS_Current()->modref_list) return WIN95;
138         return WIN31; /* FIXME: hmm, look at DDB.version ? */
139     }
140     peheader = PE_HEADER(PROCESS_Current()->exe_modref->module);
141     if (peheader->OptionalHeader.MajorSubsystemVersion == 4) {
142         /* FIXME: check probably not 100% good, verify with win98 too */
143         if (peheader->OptionalHeader.MajorOperatingSystemVersion == 4)
144             return NT40;
145         return WIN95;
146     }
147     if (peheader->OptionalHeader.MajorSubsystemVersion == 3)
148     {
149         /* Win3.10 */
150         if (peheader->OptionalHeader.MinorSubsystemVersion <= 11) return WIN31;
151         /* NT 3.51 */
152         if (peheader->OptionalHeader.MinorSubsystemVersion == 50) return NT351;
153         if (peheader->OptionalHeader.MinorSubsystemVersion == 51) return NT351;
154     }
155     if (peheader->OptionalHeader.MajorSubsystemVersion)
156         ERR(ver,"unknown subsystem version: %04x.%04x, please report.\n",
157             peheader->OptionalHeader.MajorSubsystemVersion,
158             peheader->OptionalHeader.MinorSubsystemVersion );
159     return defaultWinVersion;
160 }
161
162
163 /**********************************************************************
164  *         VERSION_GetVersionName
165  */
166 char *VERSION_GetVersionName()
167 {
168   WINDOWS_VERSION ver = VERSION_GetVersion();
169   switch(ver)
170     {
171     case WIN31:
172       return "Windows 3.1";
173     case WIN95:  
174       return "Windows 95";
175     case NT351:
176       return "Windows NT 3.51";
177     case NT40:
178       return "Windows NT 4.0";
179     default:
180       FIXME(ver,"Windows version %d not named",ver);
181       return "Windows <Unknown>";
182     }
183 }
184
185 /***********************************************************************
186  *         GetVersion16   (KERNEL.3)
187  */
188 LONG WINAPI GetVersion16(void)
189 {
190     WINDOWS_VERSION ver = VERSION_GetVersion();
191     return VersionData[ver].getVersion16;
192 }
193
194
195 /***********************************************************************
196  *         GetVersion32   (KERNEL32.427)
197  */
198 LONG WINAPI GetVersion(void)
199 {
200     WINDOWS_VERSION ver = VERSION_GetVersion();
201     return VersionData[ver].getVersion32;
202 }
203
204
205 /***********************************************************************
206  *         GetVersionEx16   (KERNEL.149)
207  */
208 BOOL16 WINAPI GetVersionEx16(OSVERSIONINFO16 *v)
209 {
210     WINDOWS_VERSION ver = VERSION_GetVersion();
211     if (v->dwOSVersionInfoSize != sizeof(OSVERSIONINFO16))
212     {
213         WARN(ver,"wrong OSVERSIONINFO size from app");
214         return FALSE;
215     }
216     v->dwMajorVersion = VersionData[ver].getVersionEx.dwMajorVersion;
217     v->dwMinorVersion = VersionData[ver].getVersionEx.dwMinorVersion;
218     v->dwBuildNumber  = VersionData[ver].getVersionEx.dwBuildNumber;
219     v->dwPlatformId   = VersionData[ver].getVersionEx.dwPlatformId;
220     strcpy( v->szCSDVersion, VersionData[ver].getVersionEx.szCSDVersion );
221     return TRUE;
222 }
223
224
225 /***********************************************************************
226  *         GetVersionEx32A   (KERNEL32.428)
227  */
228 BOOL WINAPI GetVersionExA(OSVERSIONINFOA *v)
229 {
230     WINDOWS_VERSION ver = VERSION_GetVersion();
231     if (v->dwOSVersionInfoSize != sizeof(OSVERSIONINFOA))
232     {
233         WARN(ver,"wrong OSVERSIONINFO size from app");
234         return FALSE;
235     }
236     v->dwMajorVersion = VersionData[ver].getVersionEx.dwMajorVersion;
237     v->dwMinorVersion = VersionData[ver].getVersionEx.dwMinorVersion;
238     v->dwBuildNumber  = VersionData[ver].getVersionEx.dwBuildNumber;
239     v->dwPlatformId   = VersionData[ver].getVersionEx.dwPlatformId;
240     strcpy( v->szCSDVersion, VersionData[ver].getVersionEx.szCSDVersion );
241     return TRUE;
242 }
243
244
245 /***********************************************************************
246  *         GetVersionEx32W   (KERNEL32.429)
247  */
248 BOOL WINAPI GetVersionExW(OSVERSIONINFOW *v)
249 {
250     WINDOWS_VERSION ver = VERSION_GetVersion();
251
252     if (v->dwOSVersionInfoSize!=sizeof(OSVERSIONINFOW))
253     {
254         WARN(ver,"wrong OSVERSIONINFO size from app");
255         return FALSE;
256     }
257     v->dwMajorVersion = VersionData[ver].getVersionEx.dwMajorVersion;
258     v->dwMinorVersion = VersionData[ver].getVersionEx.dwMinorVersion;
259     v->dwBuildNumber  = VersionData[ver].getVersionEx.dwBuildNumber;
260     v->dwPlatformId   = VersionData[ver].getVersionEx.dwPlatformId;
261     lstrcpyAtoW( v->szCSDVersion, VersionData[ver].getVersionEx.szCSDVersion );
262     return TRUE;
263 }
264
265
266 /***********************************************************************
267  *          GetWinFlags   (KERNEL.132)
268  */
269 DWORD WINAPI GetWinFlags16(void)
270 {
271   static const long cpuflags[5] =
272     { WF_CPU086, WF_CPU186, WF_CPU286, WF_CPU386, WF_CPU486 };
273   SYSTEM_INFO si;
274   OSVERSIONINFOA ovi;
275   DWORD result;
276
277   GetSystemInfo(&si);
278
279   /* There doesn't seem to be any Pentium flag.  */
280   result = cpuflags[MIN (si.wProcessorLevel, 4)];
281
282   switch(Options.mode)
283   {
284   case MODE_STANDARD:
285       result |= WF_STANDARD | WF_PMODE | WF_80x87;
286       break;
287
288   case MODE_ENHANCED:
289       result |= WF_ENHANCED | WF_PMODE | WF_80x87 | WF_PAGING;
290       break;
291
292   default:
293       ERR(ver, "Unknown mode set? This shouldn't happen. Check GetWinFlags()!\n");
294       break;
295   }
296   if (si.wProcessorLevel >= 4) result |= WF_HASCPUID;
297   ovi.dwOSVersionInfoSize = sizeof(ovi);
298   GetVersionExA(&ovi);
299   if (ovi.dwPlatformId == VER_PLATFORM_WIN32_NT)
300       result |= WF_WIN32WOW; /* undocumented WF_WINNT */
301   return result;
302 }
303
304
305 /***********************************************************************
306  *          GetWinDebugInfo   (KERNEL.355)
307  */
308 BOOL16 WINAPI GetWinDebugInfo16(WINDEBUGINFO *lpwdi, UINT16 flags)
309 {
310     FIXME(ver, "(%8lx,%d): stub returning 0\n",
311           (unsigned long)lpwdi, flags);
312     /* 0 means not in debugging mode/version */
313     /* Can this type of debugging be used in wine ? */
314     /* Constants: WDI_OPTIONS WDI_FILTER WDI_ALLOCBREAK */
315     return 0;
316 }
317
318
319 /***********************************************************************
320  *          SetWinDebugInfo   (KERNEL.356)
321  */
322 BOOL16 WINAPI SetWinDebugInfo16(WINDEBUGINFO *lpwdi)
323 {
324     FIXME(ver, "(%8lx): stub returning 0\n", (unsigned long)lpwdi);
325     /* 0 means not in debugging mode/version */
326     /* Can this type of debugging be used in wine ? */
327     /* Constants: WDI_OPTIONS WDI_FILTER WDI_ALLOCBREAK */
328     return 0;
329 }
330
331
332 /***********************************************************************
333  *           DebugFillBuffer                    (KERNEL.329)
334  *
335  * TODO:
336  * Should fill lpBuffer only if DBO_BUFFERFILL has been set by SetWinDebugInfo()
337  */
338 void WINAPI DebugFillBuffer(LPSTR lpBuffer, WORD wBytes)
339 {
340         memset(lpBuffer, DBGFILL_BUFFER, wBytes);
341 }
342
343 /***********************************************************************
344  *           DiagQuery                          (KERNEL.339)
345  *
346  * returns TRUE if Win called with "/b" (bootlog.txt)
347  */
348 BOOL16 WINAPI DiagQuery16()
349 {
350         /* perhaps implement a Wine "/b" command line flag sometime ? */
351         return FALSE;
352 }
353
354 /***********************************************************************
355  *           DiagOutput                         (KERNEL.340)
356  *
357  * writes a debug string into <windir>\bootlog.txt
358  */
359 void WINAPI DiagOutput16(LPCSTR str)
360 {
361         /* FIXME */
362         DPRINTF("DIAGOUTPUT:%s\n", debugstr_a(str));
363 }
364
365 /***********************************************************************
366  *           OaBuildVersion           [OLEAUT32.170]
367  */
368 UINT WINAPI OaBuildVersion()
369 {
370     WINDOWS_VERSION ver = VERSION_GetVersion();
371
372     FIXME(ver, "Please report to a.mohr@mailto.de if you get version error messages !\n");
373     switch(VersionData[ver].getVersion32)
374     {
375         case 0x80000a03: /* Win 3.1 */
376                 return 0x140fd1; /* from Win32s 1.1e */
377         case 0xc0000004: /* Win 95 */
378                 return 0x1e10a9; /* some older version: 0x0a0bd3 */
379         case 0x04213303: /* NT 3.51 */
380                 FIXME(ver, "NT 3.51 version value unknown !\n");
381                 return 0x1e10a9; /* value borrowed from Win95 */
382         case 0x05650004: /* NT 4.0 */
383                 return 0x141016;
384         default:
385                 return 0x0;
386     }
387 }
388 /***********************************************************************
389  *        VERSION_OsIsUnicode   [internal]
390  *
391  * NOTES
392  *   some functions getting sometimes LPSTR sometimes LPWSTR...
393  *
394  */
395 BOOL VERSION_OsIsUnicode(void)
396 {
397     switch(VERSION_GetVersion())
398     {
399     case NT351:
400     case NT40:
401         return TRUE;
402     default:
403         return FALSE;
404     }
405 }