Release 980215
[wine] / misc / version.c
1 /*
2  * Windows version functions
3  *
4  * Copyright 1997 Alexandre Julliard
5  * Copyright 1997 Marcus Meissner
6  */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include "windows.h"
11 #include "winbase.h"
12 #include "process.h"
13 #include "options.h"
14
15 typedef enum
16 {
17     WIN31, /* Windows 3.1 */
18     WIN95, /* Windows 95 */
19     NT351, /* Windows NT 3.51 */
20     NT40,  /* Windows NT 4.0 */
21     NB_VERSIONS
22 } VERSION;
23
24 typedef struct
25 {
26     LONG             getVersion16; 
27     LONG             getVersion32;
28     OSVERSIONINFO32A getVersionEx;
29 } VERSION_DATA;
30
31
32 /* FIXME: compare values below with original and fix */
33 static const VERSION_DATA VersionData[NB_VERSIONS] =
34 {
35     /* WIN31 */
36     {
37         MAKELONG( 0x0a03, 0x0616 ), /* DOS 6.22 */
38         MAKELONG( 0x0a03, 0x8000 ),
39         {
40             sizeof(OSVERSIONINFO32A), 3, 10, 0,
41             VER_PLATFORM_WIN32s, "Win32s 1.3" 
42         }
43     },
44     /* WIN95 */
45     {
46         0x07005F03,
47         0xC0000004,
48         {
49             sizeof(OSVERSIONINFO32A), 4, 0, 0x40003B6,
50             VER_PLATFORM_WIN32_WINDOWS, "Win95"
51         }
52     },
53     /* NT351 */
54     {
55         0x05000A03,
56         0x04213303,
57         {
58             sizeof(OSVERSIONINFO32A), 3, 51, 0x421,
59             VER_PLATFORM_WIN32_NT, "Service Pack 2"
60         }
61     },
62     /* NT40 */
63     {
64         0x05000A03,
65         0x05650004,
66         {
67             sizeof(OSVERSIONINFO32A), 4, 0, 0x565,
68             VER_PLATFORM_WIN32_NT, "Service Pack 3"
69         }
70     }
71 };
72
73 static const char *VersionNames[NB_VERSIONS] =
74 {
75     "win31",
76     "win95",
77     "nt351",
78     "nt40"
79 };
80
81 /* the current version has not been autodetected but forced via cmdline */
82 static BOOL32 versionForced = FALSE;
83 static VERSION defaultVersion = WIN31;
84
85
86 /**********************************************************************
87  *         VERSION_ParseVersion
88  */
89 void VERSION_ParseVersion( char *arg )
90 {
91     int i;
92     for (i = 0; i < NB_VERSIONS; i++)
93     {
94         if (!strcmp( VersionNames[i], arg ))
95         {
96             defaultVersion = (VERSION)i;
97             versionForced = TRUE;
98             return;
99         }
100     }
101     fprintf( stderr, "Invalid winver value '%s' specified.\n", arg );
102     fprintf( stderr, "Valid versions are:" );
103     for (i = 0; i < NB_VERSIONS; i++)
104         fprintf( stderr, " '%s'%c", VersionNames[i],
105                  (i == NB_VERSIONS - 1) ? '\n' : ',' );
106 }
107
108
109 /**********************************************************************
110  *         VERSION_get_version
111  */
112 static VERSION VERSION_GetVersion(void)
113 {
114     LPIMAGE_NT_HEADERS peheader;        
115
116     if (versionForced) /* user has overridden any sensible checks */
117         return defaultVersion;
118     if (!PROCESS_Current()->exe_modref)
119     {
120         /* HACK: if we have loaded a PE image into this address space,
121          * we are probably using thunks, so Win95 is our best bet
122          */
123         if (PROCESS_Current()->modref_list) return WIN95;
124         return WIN31; /* FIXME: hmm, look at DDB.version ? */
125     }
126     peheader = PE_HEADER(PROCESS_Current()->exe_modref->module);
127     if (peheader->OptionalHeader.MajorSubsystemVersion == 4)
128         /* FIXME: NT4 has the same majorversion; add a check here for it. */
129         return WIN95;
130     if (peheader->OptionalHeader.MajorSubsystemVersion == 3)
131     {
132         /* Win3.10 */
133         if (peheader->OptionalHeader.MinorSubsystemVersion <= 11) return WIN31;
134         /* NT 3.51 */
135         if (peheader->OptionalHeader.MinorSubsystemVersion == 51) return NT351;
136     }
137     fprintf(stderr,"VERSION_GetVersion: unknown subsystem version: %04x.%04x, please report.\n",
138             peheader->OptionalHeader.MajorSubsystemVersion,
139             peheader->OptionalHeader.MinorSubsystemVersion );
140     return defaultVersion;
141 }
142
143
144 /***********************************************************************
145  *         GetVersion16   (KERNEL.3)
146  */
147 LONG WINAPI GetVersion16(void)
148 {
149     VERSION ver = VERSION_GetVersion();
150     return VersionData[ver].getVersion16;
151 }
152
153
154 /***********************************************************************
155  *         GetVersion32   (KERNEL32.427)
156  */
157 LONG WINAPI GetVersion32(void)
158 {
159     VERSION ver = VERSION_GetVersion();
160     return VersionData[ver].getVersion32;
161 }
162
163
164 /***********************************************************************
165  *         GetVersionEx32A   (KERNEL32.428)
166  */
167 BOOL32 WINAPI GetVersionEx32A(OSVERSIONINFO32A *v)
168 {
169     VERSION ver = VERSION_GetVersion();
170     if (v->dwOSVersionInfoSize != sizeof(OSVERSIONINFO32A))
171     {
172         fprintf(stderr,"wrong OSVERSIONINFO size from app");
173         return FALSE;
174     }
175     v->dwMajorVersion = VersionData[ver].getVersionEx.dwMajorVersion;
176     v->dwMinorVersion = VersionData[ver].getVersionEx.dwMinorVersion;
177     v->dwBuildNumber  = VersionData[ver].getVersionEx.dwBuildNumber;
178     v->dwPlatformId   = VersionData[ver].getVersionEx.dwPlatformId;
179     strcpy( v->szCSDVersion, VersionData[ver].getVersionEx.szCSDVersion );
180     return TRUE;
181 }
182
183
184 /***********************************************************************
185  *         GetVersionEx32W   (KERNEL32.429)
186  */
187 BOOL32 WINAPI GetVersionEx32W(OSVERSIONINFO32W *v)
188 {
189     VERSION ver = VERSION_GetVersion();
190     if (v->dwOSVersionInfoSize!=sizeof(OSVERSIONINFO32W))
191     {
192         fprintf(stderr,"wrong OSVERSIONINFO size from app");
193         return FALSE;
194     }
195     v->dwMajorVersion = VersionData[ver].getVersionEx.dwMajorVersion;
196     v->dwMinorVersion = VersionData[ver].getVersionEx.dwMinorVersion;
197     v->dwBuildNumber  = VersionData[ver].getVersionEx.dwBuildNumber;
198     v->dwPlatformId   = VersionData[ver].getVersionEx.dwPlatformId;
199     lstrcpyAtoW( v->szCSDVersion, VersionData[ver].getVersionEx.szCSDVersion );
200     return TRUE;
201 }
202
203
204 /***********************************************************************
205  *          GetWinFlags   (KERNEL.132)
206  */
207 DWORD WINAPI GetWinFlags(void)
208 {
209   static const long cpuflags[5] =
210     { WF_CPU086, WF_CPU186, WF_CPU286, WF_CPU386, WF_CPU486 };
211   SYSTEM_INFO si;
212   OSVERSIONINFO32A ovi;
213   DWORD result;
214
215   GetSystemInfo(&si);
216
217   /* There doesn't seem to be any Pentium flag.  */
218   result = cpuflags[MIN (si.wProcessorLevel, 4)];
219
220   switch(Options.mode)
221   {
222   case MODE_STANDARD:
223       result |= WF_STANDARD | WF_PMODE | WF_80x87;
224       break;
225
226   case MODE_ENHANCED:
227       result |= WF_ENHANCED | WF_PMODE | WF_80x87 | WF_PAGING;
228       break;
229
230   default:
231       fprintf(stderr, "Unknown mode set? This shouldn't happen. Check GetWinFlags()!\n");
232       break;
233   }
234   if (si.wProcessorLevel >= 4) result |= WF_HASCPUID;
235   ovi.dwOSVersionInfoSize = sizeof(ovi);
236   GetVersionEx32A(&ovi);
237   if (ovi.dwPlatformId == VER_PLATFORM_WIN32_NT)
238       result |= WF_WIN32WOW; /* undocumented WF_WINNT */
239   return result;
240 }
241
242
243 /***********************************************************************
244  *          GetWinDebugInfo   (KERNEL.355)
245  */
246 BOOL16 WINAPI GetWinDebugInfo(WINDEBUGINFO *lpwdi, UINT16 flags)
247 {
248     printf("GetWinDebugInfo(%8lx,%d) stub returning 0\n",
249            (unsigned long)lpwdi, flags);
250     /* 0 means not in debugging mode/version */
251     /* Can this type of debugging be used in wine ? */
252     /* Constants: WDI_OPTIONS WDI_FILTER WDI_ALLOCBREAK */
253     return 0;
254 }
255
256
257 /***********************************************************************
258  *          SetWinDebugInfo   (KERNEL.356)
259  */
260 BOOL16 WINAPI SetWinDebugInfo(WINDEBUGINFO *lpwdi)
261 {
262     printf("SetWinDebugInfo(%8lx) stub returning 0\n", (unsigned long)lpwdi);
263     /* 0 means not in debugging mode/version */
264     /* Can this type of debugging be used in wine ? */
265     /* Constants: WDI_OPTIONS WDI_FILTER WDI_ALLOCBREAK */
266     return 0;
267 }
268
269
270 /***********************************************************************
271  *           DebugFillBuffer                    (KERNEL.329)
272  *
273  * TODO:
274  * Should fill lpBuffer only if DBO_BUFFERFILL has been set by SetWinDebugInfo()
275  */
276 void WINAPI DebugFillBuffer(LPSTR lpBuffer, WORD wBytes)
277 {
278         memset(lpBuffer, DBGFILL_BUFFER, wBytes);
279 }
280
281 /***********************************************************************
282  *           DiagQuery                          (KERNEL.339)
283  *
284  * returns TRUE if Win called with "/b" (bootlog.txt)
285  */
286 BOOL16 WINAPI DiagQuery()
287 {
288         /* perhaps implement a Wine "/b" command line flag sometime ? */
289         return FALSE;
290 }
291
292 /***********************************************************************
293  *           DiagOutput                         (KERNEL.340)
294  *
295  * writes a debug string into <windir>\bootlog.txt
296  */
297 void WINAPI DiagOutput()
298 {
299 }