Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 1 | /* |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 2 | * Windows and DOS version functions |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 3 | * |
| 4 | * Copyright 1997 Alexandre Julliard |
| 5 | * Copyright 1997 Marcus Meissner |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 6 | * Copyright 1998 Patrik Stridvall |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 7 | * Copyright 1998,2003 Andreas Mohr |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 8 | * |
| 9 | * This library is free software; you can redistribute it and/or |
| 10 | * modify it under the terms of the GNU Lesser General Public |
| 11 | * License as published by the Free Software Foundation; either |
| 12 | * version 2.1 of the License, or (at your option) any later version. |
| 13 | * |
| 14 | * This library is distributed in the hope that it will be useful, |
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 17 | * Lesser General Public License for more details. |
| 18 | * |
| 19 | * You should have received a copy of the GNU Lesser General Public |
| 20 | * License along with this library; if not, write to the Free Software |
| 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 22 | */ |
| 23 | |
Patrik Stridvall | 57bf450 | 2002-08-26 21:53:24 +0000 | [diff] [blame] | 24 | #include "config.h" |
| 25 | #include "wine/port.h" |
| 26 | |
Alexandre Julliard | 03468f7 | 1998-02-15 19:40:49 +0000 | [diff] [blame] | 27 | #include <string.h> |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 28 | #include <stdlib.h> |
Jeremy White | d3e22d9 | 2000-02-10 19:03:02 +0000 | [diff] [blame] | 29 | #include <stdio.h> |
| 30 | #include "windef.h" |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 31 | #include "winbase.h" |
Jeremy White | d3e22d9 | 2000-02-10 19:03:02 +0000 | [diff] [blame] | 32 | #include "wingdi.h" |
Marcus Meissner | 04c3e1d | 1999-02-19 10:37:02 +0000 | [diff] [blame] | 33 | #include "winuser.h" |
Patrik Stridvall | 9c1de6d | 2002-09-12 22:07:02 +0000 | [diff] [blame] | 34 | #include "winternl.h" |
Alexandre Julliard | 81bdcf1 | 2002-09-13 17:47:44 +0000 | [diff] [blame] | 35 | #include "winerror.h" |
Marcus Meissner | 04c3e1d | 1999-02-19 10:37:02 +0000 | [diff] [blame] | 36 | #include "wine/winbase16.h" |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 37 | #include "module.h" |
Alexandre Julliard | 81bdcf1 | 2002-09-13 17:47:44 +0000 | [diff] [blame] | 38 | #include "wine/unicode.h" |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 39 | #include "wine/debug.h" |
Eric Pouech | 051f871 | 2003-03-21 00:34:36 +0000 | [diff] [blame] | 40 | #include "ntdll_misc.h" |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 41 | |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 42 | WINE_DEFAULT_DEBUG_CHANNEL(ver); |
Alexandre Julliard | d586dc9 | 2000-08-14 14:35:01 +0000 | [diff] [blame] | 43 | |
| 44 | typedef enum |
| 45 | { |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 46 | WIN20, /* Windows 2.0 */ |
| 47 | WIN30, /* Windows 3.0 */ |
| 48 | WIN31, /* Windows 3.1 */ |
Alexandre Julliard | d586dc9 | 2000-08-14 14:35:01 +0000 | [diff] [blame] | 49 | WIN95, /* Windows 95 */ |
| 50 | WIN98, /* Windows 98 */ |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 51 | WINME, /* Windows Me */ |
Alexandre Julliard | d586dc9 | 2000-08-14 14:35:01 +0000 | [diff] [blame] | 52 | NT351, /* Windows NT 3.51 */ |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 53 | NT40, /* Windows NT 4.0 */ |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 54 | NT2K, /* Windows 2000 */ |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 55 | WINXP, /* Windows XP */ |
Alexandre Julliard | d586dc9 | 2000-08-14 14:35:01 +0000 | [diff] [blame] | 56 | NB_WINDOWS_VERSIONS |
| 57 | } WINDOWS_VERSION; |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 58 | |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 59 | typedef struct |
| 60 | { |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 61 | char human_readable[32]; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 62 | LONG getVersion16; |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 63 | LONG getVersion32; |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 64 | OSVERSIONINFOEXA getVersionEx; |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 65 | } VERSION_DATA; |
| 66 | |
Andreas Mohr | e6b031b | 2002-05-25 21:06:37 +0000 | [diff] [blame] | 67 | /* FIXME: compare values below with original and fix. |
| 68 | * An *excellent* win9x version page (ALL versions !) |
| 69 | * can be found at members.aol.com/axcel216/ver.htm */ |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 70 | static VERSION_DATA VersionData[NB_WINDOWS_VERSIONS] = |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 71 | { |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 72 | /* WIN20 FIXME: verify values */ |
| 73 | { |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 74 | "Windows 2.0", |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 75 | MAKELONG( 0x0002, 0x0303 ), /* assume DOS 3.3 */ |
Andreas Mohr | e6b031b | 2002-05-25 21:06:37 +0000 | [diff] [blame] | 76 | MAKELONG( 0x0002, 0x8000 ), |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 77 | { |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 78 | /* yes, sizeof(OSVERSIONINFOA) is correct here |
| 79 | * (in case of OSVERSIONINFOEXA application request, |
| 80 | * we adapt it dynamically). */ |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 81 | sizeof(OSVERSIONINFOA), 2, 0, 0, |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 82 | VER_PLATFORM_WIN32s, "Win32s 1.3", |
| 83 | 0, 0, 0, 0, 0 |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 84 | } |
| 85 | }, |
| 86 | /* WIN30 FIXME: verify values */ |
| 87 | { |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 88 | "Windows 3.0", |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 89 | MAKELONG( 0x0003, 0x0500 ), /* assume DOS 5.00 */ |
| 90 | MAKELONG( 0x0003, 0x8000 ), |
| 91 | { |
| 92 | sizeof(OSVERSIONINFOA), 3, 0, 0, |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 93 | VER_PLATFORM_WIN32s, "Win32s 1.3", |
| 94 | 0, 0, 0, 0, 0 |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 95 | } |
| 96 | }, |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 97 | /* WIN31 */ |
| 98 | { |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 99 | "Windows 3.1", |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 100 | MAKELONG( 0x0a03, 0x0616 ), /* DOS 6.22 */ |
| 101 | MAKELONG( 0x0a03, 0x8000 ), |
| 102 | { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 103 | sizeof(OSVERSIONINFOA), 3, 10, 0, |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 104 | VER_PLATFORM_WIN32s, "Win32s 1.3", |
| 105 | 0, 0, 0, 0, 0 |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 106 | } |
| 107 | }, |
| 108 | /* WIN95 */ |
| 109 | { |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 110 | "Windows 95", |
Marcus Meissner | 099c159 | 2001-10-23 19:55:11 +0000 | [diff] [blame] | 111 | 0x07005F03, |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 112 | 0xC0000004, |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 113 | { |
| 114 | /* Win95: 4, 0, 0x40003B6, "" |
| 115 | * Win95sp1: 4, 0, 0x40003B6, " A " (according to doc) |
| 116 | * Win95osr2: 4, 0, 0x4000457, " B " (according to doc) |
| 117 | * Win95osr2.1: 4, 3, 0x40304BC, " B " (according to doc) |
| 118 | * Win95osr2.5: 4, 3, 0x40304BE, " C " (according to doc) |
| 119 | * Win95a/b can be discerned via regkey SubVersionNumber |
| 120 | * See also: |
| 121 | * http://support.microsoft.com/support/kb/articles/q158/2/38.asp |
| 122 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 123 | sizeof(OSVERSIONINFOA), 4, 0, 0x40003B6, |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 124 | VER_PLATFORM_WIN32_WINDOWS, "", |
| 125 | 0, 0, 0, 0, 0 |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 126 | } |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 127 | }, |
Andreas Mohr | e6b031b | 2002-05-25 21:06:37 +0000 | [diff] [blame] | 128 | /* WIN98 (second edition) */ |
Ian Schmidt | d736ef4 | 1999-07-18 15:33:25 +0000 | [diff] [blame] | 129 | { |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 130 | "Windows 98 SE", |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 131 | 0x070A5F03, |
| 132 | 0xC0000A04, |
| 133 | { |
Andreas Mohr | e6b031b | 2002-05-25 21:06:37 +0000 | [diff] [blame] | 134 | /* Win98: 4, 10, 0x40A07CE, " " 4.10.1998 |
| 135 | * Win98SE: 4, 10, 0x40A08AE, " A " 4.10.2222 |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 136 | */ |
Andreas Mohr | e6b031b | 2002-05-25 21:06:37 +0000 | [diff] [blame] | 137 | sizeof(OSVERSIONINFOA), 4, 10, 0x40A08AE, |
| 138 | VER_PLATFORM_WIN32_WINDOWS, " A ", |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 139 | 0, 0, 0, 0, 0 |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 140 | } |
| 141 | }, |
| 142 | /* WINME */ |
| 143 | { |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 144 | "Windows ME", |
Andreas Mohr | e6b031b | 2002-05-25 21:06:37 +0000 | [diff] [blame] | 145 | 0x08005F03, |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 146 | 0xC0005A04, |
| 147 | { |
| 148 | sizeof(OSVERSIONINFOA), 4, 90, 0x45A0BB8, |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 149 | VER_PLATFORM_WIN32_WINDOWS, " ", |
| 150 | 0, 0, 0, 0, 0 |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 151 | } |
Ian Schmidt | d736ef4 | 1999-07-18 15:33:25 +0000 | [diff] [blame] | 152 | }, |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 153 | /* NT351 */ |
| 154 | { |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 155 | "Windows NT 3.51", |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 156 | 0x05000A03, |
| 157 | 0x04213303, |
| 158 | { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 159 | sizeof(OSVERSIONINFOA), 3, 51, 0x421, |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 160 | VER_PLATFORM_WIN32_NT, "Service Pack 2", |
| 161 | 0, 0, 0, 0, 0 |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 162 | } |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 163 | }, |
| 164 | /* NT40 */ |
| 165 | { |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 166 | "Windows NT 4.0", |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 167 | 0x05000A03, |
| 168 | 0x05650004, |
| 169 | { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 170 | sizeof(OSVERSIONINFOA), 4, 0, 0x565, |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 171 | VER_PLATFORM_WIN32_NT, "Service Pack 6", |
| 172 | 6, 0, 0, VER_NT_WORKSTATION, 0 |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 173 | } |
| 174 | }, |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 175 | /* NT2K */ |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 176 | { |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 177 | "Windows 2000", |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 178 | 0x05005F03, |
| 179 | 0x08930005, |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 180 | { |
| 181 | sizeof(OSVERSIONINFOA), 5, 0, 0x893, |
Vincent Béron | d3ac422 | 2003-04-19 02:47:56 +0000 | [diff] [blame] | 182 | VER_PLATFORM_WIN32_NT, "Service Pack 3", |
| 183 | 3, 0, 0, VER_NT_WORKSTATION, 30 /* FIXME: Great, a reserved field with a value! */ |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 184 | } |
| 185 | }, |
| 186 | /* WINXP */ |
| 187 | { |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 188 | "Windows XP", |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 189 | 0x05005F03, /* Assuming DOS 5 like the other NT */ |
| 190 | 0x0A280105, |
| 191 | { |
| 192 | sizeof(OSVERSIONINFOA), 5, 1, 0xA28, |
Vincent Béron | d3ac422 | 2003-04-19 02:47:56 +0000 | [diff] [blame] | 193 | VER_PLATFORM_WIN32_NT, "Service Pack 1", |
| 194 | 1, 0, VER_SUITE_SINGLEUSERTS, VER_NT_WORKSTATION, 30 /* FIXME: Great, a reserved field with a value! */ |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 195 | } |
| 196 | } |
| 197 | }; |
| 198 | |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 199 | static const char *WinVersionNames[NB_WINDOWS_VERSIONS] = |
Andreas Mohr | c3350c5 | 2000-11-30 01:29:45 +0000 | [diff] [blame] | 200 | { /* no spaces in here ! */ |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 201 | "win20", |
| 202 | "win30", |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 203 | "win31", |
| 204 | "win95", |
Ian Schmidt | d736ef4 | 1999-07-18 15:33:25 +0000 | [diff] [blame] | 205 | "win98", |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 206 | "winme", |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 207 | "nt351", |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 208 | "nt40", |
Francois Gouget | 4ae7195 | 2001-11-06 00:49:48 +0000 | [diff] [blame] | 209 | "win2000,win2k,nt2k,nt2000", |
| 210 | "winxp" |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 211 | }; |
| 212 | |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 213 | /* if one of the following dlls is importing ntdll the windows |
| 214 | version autodetection switches wine to unicode (nt 3.51 or 4.0) */ |
| 215 | static char * special_dlls[] = |
| 216 | { |
Alexandre Julliard | 1df1883 | 2002-09-06 18:37:48 +0000 | [diff] [blame] | 217 | "comdlg32.dll", |
| 218 | "comctl32.dll", |
| 219 | "shell32.dll", |
| 220 | "ole32.dll", |
| 221 | "rpcrt4.dll", |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 222 | NULL |
| 223 | }; |
| 224 | |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 225 | /* the current version has not been autodetected but forced via cmdline */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 226 | static BOOL versionForced = FALSE; |
Andreas Mohr | e6b031b | 2002-05-25 21:06:37 +0000 | [diff] [blame] | 227 | static WINDOWS_VERSION forcedWinVersion = WIN31; /* init value irrelevant */ |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 228 | |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 229 | /********************************************************************** |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 230 | * VERSION_ParseWinVersion |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 231 | */ |
Alexandre Julliard | 8c08ceb | 2002-05-23 19:35:18 +0000 | [diff] [blame] | 232 | static void VERSION_ParseWinVersion( const char *arg ) |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 233 | { |
Andreas Mohr | c3350c5 | 2000-11-30 01:29:45 +0000 | [diff] [blame] | 234 | int i, len; |
| 235 | const char *pCurr, *p; |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 236 | for (i = 0; i < NB_WINDOWS_VERSIONS; i++) |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 237 | { |
Andreas Mohr | c3350c5 | 2000-11-30 01:29:45 +0000 | [diff] [blame] | 238 | pCurr = WinVersionNames[i]; |
| 239 | /* iterate through all winver aliases separated by comma */ |
| 240 | do { |
| 241 | p = strchr(pCurr, ','); |
| 242 | len = p ? (int)p - (int)pCurr : strlen(pCurr); |
| 243 | if ( (!strncmp( pCurr, arg, len )) && (arg[len] == '\0') ) |
| 244 | { |
Andreas Mohr | e6b031b | 2002-05-25 21:06:37 +0000 | [diff] [blame] | 245 | forcedWinVersion = (WINDOWS_VERSION)i; |
Andreas Mohr | c3350c5 | 2000-11-30 01:29:45 +0000 | [diff] [blame] | 246 | versionForced = TRUE; |
| 247 | return; |
| 248 | } |
| 249 | pCurr = p+1; |
| 250 | } while (p); |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 251 | } |
Alexandre Julliard | 8c08ceb | 2002-05-23 19:35:18 +0000 | [diff] [blame] | 252 | MESSAGE("Invalid Windows version value '%s' specified in config file.\n", arg ); |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 253 | MESSAGE("Valid versions are:" ); |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 254 | for (i = 0; i < NB_WINDOWS_VERSIONS; i++) |
Andreas Mohr | c3350c5 | 2000-11-30 01:29:45 +0000 | [diff] [blame] | 255 | { |
| 256 | /* only list the first, "official" alias in case of aliases */ |
| 257 | pCurr = WinVersionNames[i]; |
| 258 | p = strchr(pCurr, ','); |
| 259 | len = (p) ? (int)p - (int)pCurr : strlen(pCurr); |
| 260 | |
| 261 | MESSAGE(" '%.*s'%c", len, pCurr, |
| 262 | (i == NB_WINDOWS_VERSIONS - 1) ? '\n' : ',' ); |
| 263 | } |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 264 | ExitProcess(1); |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 265 | } |
| 266 | |
| 267 | |
| 268 | /********************************************************************** |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 269 | * VERSION_ParseDosVersion |
| 270 | */ |
Alexandre Julliard | 8c08ceb | 2002-05-23 19:35:18 +0000 | [diff] [blame] | 271 | static void VERSION_ParseDosVersion( const char *arg ) |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 272 | { |
| 273 | int hi, lo; |
| 274 | if (sscanf( arg, "%d.%d", &hi, &lo ) == 2) |
| 275 | { |
| 276 | VersionData[WIN31].getVersion16 = |
| 277 | MAKELONG(LOWORD(VersionData[WIN31].getVersion16), |
| 278 | (hi<<8) + lo); |
| 279 | } |
| 280 | else |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 281 | { |
Alexandre Julliard | 8c08ceb | 2002-05-23 19:35:18 +0000 | [diff] [blame] | 282 | MESSAGE("Wrong format for DOS version in config file. Use \"x.xx\"\n"); |
Alexandre Julliard | fe08568 | 2000-03-18 21:56:10 +0000 | [diff] [blame] | 283 | ExitProcess(1); |
| 284 | } |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 285 | } |
| 286 | |
Alexandre Julliard | 8c08ceb | 2002-05-23 19:35:18 +0000 | [diff] [blame] | 287 | |
| 288 | /********************************************************************** |
Alexandre Julliard | 81bdcf1 | 2002-09-13 17:47:44 +0000 | [diff] [blame] | 289 | * VERSION_ParseVersion |
| 290 | * |
| 291 | * Parse the contents of the Version key. |
| 292 | */ |
| 293 | static void VERSION_ParseVersion( HKEY hkey, BOOL *got_win_ver, BOOL *got_dos_ver ) |
| 294 | { |
| 295 | static const WCHAR WindowsW[] = {'W','i','n','d','o','w','s',0}; |
| 296 | static const WCHAR DosW[] = {'D','O','S',0}; |
| 297 | |
| 298 | UNICODE_STRING valueW; |
| 299 | char tmp[64], buffer[50]; |
| 300 | KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)tmp; |
| 301 | DWORD count, len; |
| 302 | |
| 303 | if (!*got_win_ver) |
| 304 | { |
| 305 | RtlInitUnicodeString( &valueW, WindowsW ); |
| 306 | if (!NtQueryValueKey( hkey, &valueW, KeyValuePartialInformation, tmp, sizeof(tmp), &count )) |
| 307 | { |
| 308 | RtlUnicodeToMultiByteN( buffer, sizeof(buffer)-1, &len, |
| 309 | (WCHAR *)info->Data, info->DataLength ); |
| 310 | buffer[len] = 0; |
| 311 | VERSION_ParseWinVersion( buffer ); |
| 312 | TRACE( "got win version %s\n", WinVersionNames[forcedWinVersion] ); |
| 313 | *got_win_ver = TRUE; |
| 314 | } |
| 315 | } |
| 316 | if (!*got_dos_ver) |
| 317 | { |
| 318 | RtlInitUnicodeString( &valueW, DosW ); |
| 319 | if (!NtQueryValueKey( hkey, &valueW, KeyValuePartialInformation, tmp, sizeof(tmp), &count )) |
| 320 | { |
| 321 | RtlUnicodeToMultiByteN( buffer, sizeof(buffer)-1, &len, |
| 322 | (WCHAR *)info->Data, info->DataLength ); |
| 323 | buffer[len] = 0; |
| 324 | VERSION_ParseDosVersion( buffer ); |
| 325 | TRACE( "got dos version %lx\n", VersionData[WIN31].getVersion16 ); |
| 326 | *got_dos_ver = TRUE; |
| 327 | } |
| 328 | } |
| 329 | } |
| 330 | |
| 331 | |
| 332 | /********************************************************************** |
Alexandre Julliard | 8c08ceb | 2002-05-23 19:35:18 +0000 | [diff] [blame] | 333 | * VERSION_Init |
| 334 | */ |
Alexandre Julliard | a058584 | 2003-04-20 02:46:44 +0000 | [diff] [blame] | 335 | void VERSION_Init( const char *appname ) |
Alexandre Julliard | 8c08ceb | 2002-05-23 19:35:18 +0000 | [diff] [blame] | 336 | { |
Alexandre Julliard | 81bdcf1 | 2002-09-13 17:47:44 +0000 | [diff] [blame] | 337 | OBJECT_ATTRIBUTES attr; |
| 338 | UNICODE_STRING nameW; |
| 339 | HKEY hkey, config_key; |
Alexandre Julliard | 8c08ceb | 2002-05-23 19:35:18 +0000 | [diff] [blame] | 340 | BOOL got_win_ver = FALSE, got_dos_ver = FALSE; |
Alexandre Julliard | 81bdcf1 | 2002-09-13 17:47:44 +0000 | [diff] [blame] | 341 | static const WCHAR configW[] = {'M','a','c','h','i','n','e','\\', |
| 342 | 'S','o','f','t','w','a','r','e','\\', |
| 343 | 'W','i','n','e','\\', |
| 344 | 'W','i','n','e','\\', |
| 345 | 'C','o','n','f','i','g',0}; |
| 346 | static const WCHAR appdefaultsW[] = {'A','p','p','D','e','f','a','u','l','t','s','\\',0}; |
| 347 | static const WCHAR versionW[] = {'\\','V','e','r','s','i','o','n',0}; |
Alexandre Julliard | 8c08ceb | 2002-05-23 19:35:18 +0000 | [diff] [blame] | 348 | |
Alexandre Julliard | 81bdcf1 | 2002-09-13 17:47:44 +0000 | [diff] [blame] | 349 | attr.Length = sizeof(attr); |
| 350 | attr.RootDirectory = 0; |
| 351 | attr.ObjectName = &nameW; |
| 352 | attr.Attributes = 0; |
| 353 | attr.SecurityDescriptor = NULL; |
| 354 | attr.SecurityQualityOfService = NULL; |
| 355 | RtlInitUnicodeString( &nameW, configW ); |
| 356 | |
| 357 | if (NtOpenKey( &config_key, KEY_ALL_ACCESS, &attr )) return; |
| 358 | attr.RootDirectory = config_key; |
| 359 | |
| 360 | /* open AppDefaults\\appname\\Version key */ |
Alexandre Julliard | a058584 | 2003-04-20 02:46:44 +0000 | [diff] [blame] | 361 | if (appname && *appname) |
Alexandre Julliard | 8c08ceb | 2002-05-23 19:35:18 +0000 | [diff] [blame] | 362 | { |
Alexandre Julliard | a058584 | 2003-04-20 02:46:44 +0000 | [diff] [blame] | 363 | const char *p; |
| 364 | DWORD len; |
| 365 | WCHAR appversion[MAX_PATH+20]; |
| 366 | |
| 367 | if ((p = strrchr( appname, '/' ))) appname = p + 1; |
| 368 | if ((p = strrchr( appname, '\\' ))) appname = p + 1; |
| 369 | |
| 370 | strcpyW( appversion, appdefaultsW ); |
| 371 | len = strlenW(appversion); |
| 372 | RtlMultiByteToUnicodeN( appversion + len, sizeof(appversion) - len*sizeof(WCHAR), |
| 373 | &len, appname, strlen(appname)+1 ); |
| 374 | strcatW( appversion, versionW ); |
| 375 | TRACE( "getting version from %s\n", debugstr_w(appversion) ); |
| 376 | RtlInitUnicodeString( &nameW, appversion ); |
| 377 | |
| 378 | if (!NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr )) |
| 379 | { |
| 380 | VERSION_ParseVersion( hkey, &got_win_ver, &got_dos_ver ); |
| 381 | NtClose( hkey ); |
| 382 | } |
| 383 | if (got_win_ver && got_dos_ver) goto done; |
Alexandre Julliard | 8c08ceb | 2002-05-23 19:35:18 +0000 | [diff] [blame] | 384 | } |
| 385 | |
Alexandre Julliard | a058584 | 2003-04-20 02:46:44 +0000 | [diff] [blame] | 386 | TRACE( "getting default version\n" ); |
Alexandre Julliard | 81bdcf1 | 2002-09-13 17:47:44 +0000 | [diff] [blame] | 387 | RtlInitUnicodeString( &nameW, versionW + 1 ); |
| 388 | if (!NtOpenKey( &hkey, KEY_ALL_ACCESS, &attr )) |
Alexandre Julliard | 8c08ceb | 2002-05-23 19:35:18 +0000 | [diff] [blame] | 389 | { |
Alexandre Julliard | 81bdcf1 | 2002-09-13 17:47:44 +0000 | [diff] [blame] | 390 | VERSION_ParseVersion( hkey, &got_win_ver, &got_dos_ver ); |
| 391 | NtClose( hkey ); |
Alexandre Julliard | 8c08ceb | 2002-05-23 19:35:18 +0000 | [diff] [blame] | 392 | } |
Alexandre Julliard | 81bdcf1 | 2002-09-13 17:47:44 +0000 | [diff] [blame] | 393 | |
| 394 | done: |
| 395 | NtClose( config_key ); |
Alexandre Julliard | 8c08ceb | 2002-05-23 19:35:18 +0000 | [diff] [blame] | 396 | } |
| 397 | |
| 398 | |
Andreas Mohr | cd3278b | 1999-06-12 14:46:54 +0000 | [diff] [blame] | 399 | /********************************************************************** |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 400 | * VERSION_GetSystemDLLVersion |
Andreas Mohr | cd3278b | 1999-06-12 14:46:54 +0000 | [diff] [blame] | 401 | * |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 402 | * This function tries to figure out if a given (native) dll comes from |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 403 | * win95/98 or winnt. Since all values in the OptionalHeader are not a |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 404 | * usable hint, we test if a dll imports the ntdll. |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 405 | * This is at least working for all system dlls like comctl32, comdlg32 and |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 406 | * shell32. |
| 407 | * If you have a better idea to figure this out... |
| 408 | */ |
Alexandre Julliard | 081ee94 | 2000-08-07 04:12:41 +0000 | [diff] [blame] | 409 | static DWORD VERSION_GetSystemDLLVersion( HMODULE hmod ) |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 410 | { |
Alexandre Julliard | a5dea21 | 2002-08-09 19:57:38 +0000 | [diff] [blame] | 411 | DWORD size; |
| 412 | IMAGE_IMPORT_DESCRIPTOR *pe_imp; |
| 413 | |
| 414 | if ((pe_imp = RtlImageDirectoryEntryToData( hmod, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size ))) |
Alexandre Julliard | 081ee94 | 2000-08-07 04:12:41 +0000 | [diff] [blame] | 415 | { |
Alexandre Julliard | 081ee94 | 2000-08-07 04:12:41 +0000 | [diff] [blame] | 416 | for ( ; pe_imp->Name; pe_imp++) |
| 417 | { |
| 418 | char * name = (char *)hmod + (unsigned int)pe_imp->Name; |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 419 | TRACE("%s\n", name); |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 420 | |
Alexandre Julliard | 081ee94 | 2000-08-07 04:12:41 +0000 | [diff] [blame] | 421 | if (!strncasecmp(name, "ntdll", 5)) |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 422 | { |
Alexandre Julliard | a5dea21 | 2002-08-09 19:57:38 +0000 | [diff] [blame] | 423 | switch(RtlImageNtHeader(hmod)->OptionalHeader.MajorOperatingSystemVersion) { |
Andreas Mohr | e6b031b | 2002-05-25 21:06:37 +0000 | [diff] [blame] | 424 | case 3: |
| 425 | MESSAGE("WARNING: very old native DLL (NT 3.x) used, might cause instability.\n"); |
| 426 | return NT351; |
| 427 | case 4: return NT40; |
| 428 | case 5: return NT2K; |
| 429 | case 6: return WINXP; |
| 430 | default: |
| 431 | FIXME("Unknown DLL OS version, please report !!\n"); |
| 432 | return WINXP; |
| 433 | } |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 434 | } |
Alexandre Julliard | 081ee94 | 2000-08-07 04:12:41 +0000 | [diff] [blame] | 435 | } |
| 436 | } |
| 437 | return WIN95; |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 438 | } |
| 439 | /********************************************************************** |
| 440 | * VERSION_GetLinkedDllVersion |
| 441 | * |
| 442 | * Some version data (not reliable!): |
| 443 | * linker/OS/image/subsys |
| 444 | * |
| 445 | * x.xx/1.00/0.00/3.10 Win32s (any version ?) |
| 446 | * 2.39/1.00/0.00/3.10 Win32s freecell.exe (any version) |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 447 | * 2.50/1.00/4.00/4.00 Win32s 1.30 winhlp32.exe |
| 448 | * 2.60/3.51/3.51/3.51 NT351SP5 system dlls |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 449 | * 2.60/3.51/3.51/4.00 NT351SP5 comctl32 dll |
| 450 | * 2.xx/1.00/0.00/4.00 Win95 system files |
| 451 | * x.xx/4.00/0.00/4.00 Win95 most applications |
| 452 | * 3.10/4.00/0.00/4.00 Win98 notepad |
Andreas Mohr | e6b031b | 2002-05-25 21:06:37 +0000 | [diff] [blame] | 453 | * x.xx/5.00/5.00/4.00 Win98 system dlls (e.g. comctl32.dll) |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 454 | * x.xx/4.00/4.00/4.00 NT 4 most apps |
| 455 | * 5.12/5.00/5.00/4.00 NT4+IE5 comctl32.dll |
| 456 | * 5.12/5.00/5.00/4.00 Win98 calc |
| 457 | * x.xx/5.00/5.00/4.00 win95/win98/NT4 IE5 files |
Andreas Mohr | cd3278b | 1999-06-12 14:46:54 +0000 | [diff] [blame] | 458 | */ |
Patrik Stridvall | 57bf450 | 2002-08-26 21:53:24 +0000 | [diff] [blame] | 459 | static DWORD VERSION_GetLinkedDllVersion(void) |
Andreas Mohr | cd3278b | 1999-06-12 14:46:54 +0000 | [diff] [blame] | 460 | { |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 461 | DWORD WinVersion = NB_WINDOWS_VERSIONS; |
| 462 | PIMAGE_OPTIONAL_HEADER ophd; |
Alexandre Julliard | a5dea21 | 2002-08-09 19:57:38 +0000 | [diff] [blame] | 463 | IMAGE_NT_HEADERS *nt; |
Eric Pouech | 051f871 | 2003-03-21 00:34:36 +0000 | [diff] [blame] | 464 | ULONG count, required; |
| 465 | SYSTEM_MODULE_INFORMATION* smi; |
Andreas Mohr | cd3278b | 1999-06-12 14:46:54 +0000 | [diff] [blame] | 466 | |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 467 | /* First check the native dlls provided. These have to be |
| 468 | from one windows version */ |
Eric Pouech | 051f871 | 2003-03-21 00:34:36 +0000 | [diff] [blame] | 469 | smi = (SYSTEM_MODULE_INFORMATION*)&count; |
| 470 | LdrQueryProcessModuleInformation(smi, sizeof(count), &required); |
| 471 | smi = RtlAllocateHeap(ntdll_get_process_heap(), 0, required); |
| 472 | if (smi) |
| 473 | { |
| 474 | if (LdrQueryProcessModuleInformation(smi, required, NULL) == STATUS_SUCCESS) |
| 475 | { |
Alexandre Julliard | 915a4ba | 2003-03-30 03:08:13 +0000 | [diff] [blame] | 476 | int i, k; |
Eric Pouech | 051f871 | 2003-03-21 00:34:36 +0000 | [diff] [blame] | 477 | for (k = 0; k < smi->ModulesCount; k++) |
| 478 | { |
| 479 | nt = RtlImageNtHeader(smi->Modules[k].ImageBaseAddress); |
| 480 | ophd = &nt->OptionalHeader; |
Alexandre Julliard | 915a4ba | 2003-03-30 03:08:13 +0000 | [diff] [blame] | 481 | |
Eric Pouech | 051f871 | 2003-03-21 00:34:36 +0000 | [diff] [blame] | 482 | TRACE("%s: %02x.%02x/%02x.%02x/%02x.%02x/%02x.%02x\n", |
| 483 | &smi->Modules[k].Name[smi->Modules[k].NameOffset], |
| 484 | ophd->MajorLinkerVersion, ophd->MinorLinkerVersion, |
| 485 | ophd->MajorOperatingSystemVersion, ophd->MinorOperatingSystemVersion, |
| 486 | ophd->MajorImageVersion, ophd->MinorImageVersion, |
| 487 | ophd->MajorSubsystemVersion, ophd->MinorSubsystemVersion); |
Andreas Mohr | cd3278b | 1999-06-12 14:46:54 +0000 | [diff] [blame] | 488 | |
Alexandre Julliard | 915a4ba | 2003-03-30 03:08:13 +0000 | [diff] [blame] | 489 | /* test if it is an external (native) dll */ |
| 490 | if (smi->Modules[k].Flags & LDR_WINE_INTERNAL) continue; |
| 491 | |
Eric Pouech | 051f871 | 2003-03-21 00:34:36 +0000 | [diff] [blame] | 492 | for (i = 0; special_dlls[i]; i++) |
| 493 | { |
| 494 | /* test if it is a special dll */ |
| 495 | if (!strcasecmp(&smi->Modules[k].Name[smi->Modules[k].NameOffset], special_dlls[i])) |
| 496 | { |
| 497 | DWORD DllVersion = VERSION_GetSystemDLLVersion(smi->Modules[k].ImageBaseAddress); |
| 498 | if (WinVersion == NB_WINDOWS_VERSIONS) |
| 499 | WinVersion = DllVersion; |
| 500 | else |
| 501 | { |
| 502 | if (WinVersion != DllVersion) { |
| 503 | ERR("You mixed system DLLs from different windows versions! Expect a crash! (%s: expected version '%s', but is '%s')\n", |
| 504 | &smi->Modules[k].Name[smi->Modules[k].NameOffset], |
| 505 | VersionData[WinVersion].getVersionEx.szCSDVersion, |
| 506 | VersionData[DllVersion].getVersionEx.szCSDVersion); |
| 507 | return WIN20; /* this may let the exe exiting */ |
| 508 | } |
| 509 | } |
| 510 | break; |
| 511 | } |
| 512 | } |
| 513 | } |
| 514 | } |
| 515 | RtlFreeHeap(ntdll_get_process_heap(), 0, smi); |
| 516 | } |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 517 | |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 518 | if(WinVersion != NB_WINDOWS_VERSIONS) return WinVersion; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 519 | |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 520 | /* we are using no external system dlls, look at the exe */ |
Alexandre Julliard | a5dea21 | 2002-08-09 19:57:38 +0000 | [diff] [blame] | 521 | nt = RtlImageNtHeader(GetModuleHandleA(NULL)); |
| 522 | ophd = &nt->OptionalHeader; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 523 | |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 524 | TRACE("%02x.%02x/%02x.%02x/%02x.%02x/%02x.%02x\n", |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 525 | ophd->MajorLinkerVersion, ophd->MinorLinkerVersion, |
| 526 | ophd->MajorOperatingSystemVersion, ophd->MinorOperatingSystemVersion, |
| 527 | ophd->MajorImageVersion, ophd->MinorImageVersion, |
| 528 | ophd->MajorSubsystemVersion, ophd->MinorSubsystemVersion); |
| 529 | |
| 530 | /* special nt 3.51 */ |
| 531 | if (3 == ophd->MajorOperatingSystemVersion && 51 == ophd->MinorOperatingSystemVersion) |
| 532 | { |
| 533 | return NT351; |
Andreas Mohr | cd3278b | 1999-06-12 14:46:54 +0000 | [diff] [blame] | 534 | } |
| 535 | |
Andreas Mohr | cb45438 | 2000-11-27 01:39:05 +0000 | [diff] [blame] | 536 | /* the MajorSubsystemVersion is the only usable sign */ |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 537 | if (ophd->MajorSubsystemVersion < 4) |
| 538 | { |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 539 | if ( ophd->MajorOperatingSystemVersion == 1 |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 540 | && ophd->MinorOperatingSystemVersion == 0) |
| 541 | { |
| 542 | return WIN31; /* win32s */ |
| 543 | } |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 544 | |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 545 | if (ophd->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI) |
| 546 | return NT351; /* FIXME: NT 3.1, not tested */ |
| 547 | else |
| 548 | return WIN95; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 549 | } |
Andreas Mohr | cd3278b | 1999-06-12 14:46:54 +0000 | [diff] [blame] | 550 | |
Juergen Schmied | a72a398 | 1999-10-31 21:38:31 +0000 | [diff] [blame] | 551 | return WIN95; |
| 552 | } |
Andreas Mohr | cd3278b | 1999-06-12 14:46:54 +0000 | [diff] [blame] | 553 | |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 554 | /********************************************************************** |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 555 | * VERSION_GetVersion |
Andreas Mohr | c264f2e | 1999-04-25 10:54:16 +0000 | [diff] [blame] | 556 | * |
Andreas Mohr | 8670b6f | 1999-10-13 12:19:51 +0000 | [diff] [blame] | 557 | * WARNING !!! |
| 558 | * Don't call this function too early during the Wine init, |
| 559 | * as pdb->exe_modref (required by VERSION_GetImageVersion()) might still |
| 560 | * be NULL in such cases, which causes the winver to ALWAYS be detected |
| 561 | * as WIN31. |
| 562 | * And as we cache the winver once it has been determined, this is bad. |
| 563 | * This can happen much easier than you might think, as this function |
| 564 | * is called by EVERY GetVersion*() API ! |
| 565 | * |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 566 | */ |
Alexandre Julliard | d586dc9 | 2000-08-14 14:35:01 +0000 | [diff] [blame] | 567 | static WINDOWS_VERSION VERSION_GetVersion(void) |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 568 | { |
Andreas Mohr | b7afbd4 | 2001-10-01 20:52:37 +0000 | [diff] [blame] | 569 | static WORD winver = 0xffff; |
Alexandre Julliard | 46733de | 2000-08-09 22:31:24 +0000 | [diff] [blame] | 570 | |
Alexandre Julliard | a058584 | 2003-04-20 02:46:44 +0000 | [diff] [blame] | 571 | if (versionForced) return forcedWinVersion; /* user has overridden any sensible checks */ |
| 572 | |
Andreas Mohr | b7afbd4 | 2001-10-01 20:52:37 +0000 | [diff] [blame] | 573 | if (winver == 0xffff) /* to be determined */ |
| 574 | { |
Alexandre Julliard | a058584 | 2003-04-20 02:46:44 +0000 | [diff] [blame] | 575 | WINDOWS_VERSION retver = VERSION_GetLinkedDllVersion(); |
Alexandre Julliard | 8c08ceb | 2002-05-23 19:35:18 +0000 | [diff] [blame] | 576 | |
Alexandre Julliard | a058584 | 2003-04-20 02:46:44 +0000 | [diff] [blame] | 577 | /* cache determined value, but do not store in case of WIN31 */ |
| 578 | if (retver != WIN31) winver = retver; |
| 579 | return retver; |
Andreas Mohr | b7afbd4 | 2001-10-01 20:52:37 +0000 | [diff] [blame] | 580 | } |
Andreas Mohr | b7afbd4 | 2001-10-01 20:52:37 +0000 | [diff] [blame] | 581 | return winver; |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 582 | } |
| 583 | |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 584 | |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 585 | /*********************************************************************** |
Patrik Stridvall | 01d5e5b | 2001-07-02 19:59:40 +0000 | [diff] [blame] | 586 | * GetVersion (KERNEL.3) |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 587 | */ |
| 588 | LONG WINAPI GetVersion16(void) |
| 589 | { |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 590 | WINDOWS_VERSION ver = VERSION_GetVersion(); |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 591 | TRACE("<-- %s (%s)\n", VersionData[ver].human_readable, VersionData[ver].getVersionEx.szCSDVersion); |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 592 | return VersionData[ver].getVersion16; |
| 593 | } |
| 594 | |
| 595 | |
| 596 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 597 | * GetVersion (KERNEL32.@) |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 598 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 599 | LONG WINAPI GetVersion(void) |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 600 | { |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 601 | WINDOWS_VERSION ver = VERSION_GetVersion(); |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 602 | TRACE("<-- %s (%s)\n", VersionData[ver].human_readable, VersionData[ver].getVersionEx.szCSDVersion); |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 603 | return VersionData[ver].getVersion32; |
| 604 | } |
| 605 | |
| 606 | |
| 607 | /*********************************************************************** |
Patrik Stridvall | 01d5e5b | 2001-07-02 19:59:40 +0000 | [diff] [blame] | 608 | * GetVersionEx (KERNEL.149) |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 609 | */ |
| 610 | BOOL16 WINAPI GetVersionEx16(OSVERSIONINFO16 *v) |
| 611 | { |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 612 | WINDOWS_VERSION ver = VERSION_GetVersion(); |
James Juran | 94cd060 | 2001-05-24 18:38:49 +0000 | [diff] [blame] | 613 | if (v->dwOSVersionInfoSize < sizeof(OSVERSIONINFO16)) |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 614 | { |
James Juran | b7c2f2f | 2001-05-09 17:09:04 +0000 | [diff] [blame] | 615 | WARN("wrong OSVERSIONINFO size from app\n"); |
Morten Eriksen | 594af0d | 1999-08-14 15:53:07 +0000 | [diff] [blame] | 616 | SetLastError(ERROR_INSUFFICIENT_BUFFER); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 617 | return FALSE; |
| 618 | } |
| 619 | v->dwMajorVersion = VersionData[ver].getVersionEx.dwMajorVersion; |
| 620 | v->dwMinorVersion = VersionData[ver].getVersionEx.dwMinorVersion; |
| 621 | v->dwBuildNumber = VersionData[ver].getVersionEx.dwBuildNumber; |
| 622 | v->dwPlatformId = VersionData[ver].getVersionEx.dwPlatformId; |
| 623 | strcpy( v->szCSDVersion, VersionData[ver].getVersionEx.szCSDVersion ); |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 624 | TRACE("<-- %s (%s)\n", VersionData[ver].human_readable, VersionData[ver].getVersionEx.szCSDVersion); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 625 | return TRUE; |
| 626 | } |
| 627 | |
| 628 | |
| 629 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 630 | * GetVersionExA (KERNEL32.@) |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 631 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 632 | BOOL WINAPI GetVersionExA(OSVERSIONINFOA *v) |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 633 | { |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 634 | WINDOWS_VERSION ver = VERSION_GetVersion(); |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 635 | LPOSVERSIONINFOEXA vex; |
| 636 | |
| 637 | if (v->dwOSVersionInfoSize != sizeof(OSVERSIONINFOA) && |
| 638 | v->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXA)) |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 639 | { |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 640 | WARN("wrong OSVERSIONINFO size from app (got: %ld, expected: %d or %d)\n", |
| 641 | v->dwOSVersionInfoSize, sizeof(OSVERSIONINFOA), |
| 642 | sizeof(OSVERSIONINFOEXA)); |
Morten Eriksen | 594af0d | 1999-08-14 15:53:07 +0000 | [diff] [blame] | 643 | SetLastError(ERROR_INSUFFICIENT_BUFFER); |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 644 | return FALSE; |
| 645 | } |
| 646 | v->dwMajorVersion = VersionData[ver].getVersionEx.dwMajorVersion; |
| 647 | v->dwMinorVersion = VersionData[ver].getVersionEx.dwMinorVersion; |
| 648 | v->dwBuildNumber = VersionData[ver].getVersionEx.dwBuildNumber; |
| 649 | v->dwPlatformId = VersionData[ver].getVersionEx.dwPlatformId; |
| 650 | strcpy( v->szCSDVersion, VersionData[ver].getVersionEx.szCSDVersion ); |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 651 | if(v->dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXA)) { |
| 652 | vex = (LPOSVERSIONINFOEXA) v; |
| 653 | vex->wServicePackMajor = VersionData[ver].getVersionEx.wServicePackMajor; |
| 654 | vex->wServicePackMinor = VersionData[ver].getVersionEx.wServicePackMinor; |
| 655 | vex->wSuiteMask = VersionData[ver].getVersionEx.wSuiteMask; |
| 656 | vex->wProductType = VersionData[ver].getVersionEx.wProductType; |
| 657 | } |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 658 | TRACE("<-- %s (%s)\n", VersionData[ver].human_readable, VersionData[ver].getVersionEx.szCSDVersion); |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 659 | return TRUE; |
| 660 | } |
| 661 | |
| 662 | |
| 663 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 664 | * GetVersionExW (KERNEL32.@) |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 665 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 666 | BOOL WINAPI GetVersionExW(OSVERSIONINFOW *v) |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 667 | { |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 668 | WINDOWS_VERSION ver = VERSION_GetVersion(); |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 669 | LPOSVERSIONINFOEXW vex; |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 670 | |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 671 | if (v->dwOSVersionInfoSize != sizeof(OSVERSIONINFOW) && |
| 672 | v->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXW)) |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 673 | { |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 674 | WARN("wrong OSVERSIONINFO size from app (got: %ld, expected: %d or %d)\n", |
| 675 | v->dwOSVersionInfoSize, sizeof(OSVERSIONINFOW), |
| 676 | sizeof(OSVERSIONINFOEXW)); |
Morten Eriksen | 594af0d | 1999-08-14 15:53:07 +0000 | [diff] [blame] | 677 | SetLastError(ERROR_INSUFFICIENT_BUFFER); |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 678 | return FALSE; |
| 679 | } |
| 680 | v->dwMajorVersion = VersionData[ver].getVersionEx.dwMajorVersion; |
| 681 | v->dwMinorVersion = VersionData[ver].getVersionEx.dwMinorVersion; |
| 682 | v->dwBuildNumber = VersionData[ver].getVersionEx.dwBuildNumber; |
| 683 | v->dwPlatformId = VersionData[ver].getVersionEx.dwPlatformId; |
Alexandre Julliard | 24a62ab | 2000-11-28 22:40:56 +0000 | [diff] [blame] | 684 | MultiByteToWideChar( CP_ACP, 0, VersionData[ver].getVersionEx.szCSDVersion, -1, |
| 685 | v->szCSDVersion, sizeof(v->szCSDVersion)/sizeof(WCHAR) ); |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 686 | if(v->dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXW)) { |
| 687 | vex = (LPOSVERSIONINFOEXW) v; |
| 688 | vex->wServicePackMajor = VersionData[ver].getVersionEx.wServicePackMajor; |
| 689 | vex->wServicePackMinor = VersionData[ver].getVersionEx.wServicePackMinor; |
| 690 | vex->wSuiteMask = VersionData[ver].getVersionEx.wSuiteMask; |
| 691 | vex->wProductType = VersionData[ver].getVersionEx.wProductType; |
| 692 | } |
Andreas Mohr | 5f66b04 | 2003-04-16 23:08:33 +0000 | [diff] [blame] | 693 | TRACE("<-- %s (%s)\n", VersionData[ver].human_readable, VersionData[ver].getVersionEx.szCSDVersion); |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 694 | return TRUE; |
| 695 | } |
| 696 | |
| 697 | |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 698 | /****************************************************************************** |
| 699 | * VerifyVersionInfoA (KERNEL32.@) |
| 700 | */ |
| 701 | BOOL WINAPI VerifyVersionInfoA( LPOSVERSIONINFOEXA lpVersionInfo, DWORD dwTypeMask, |
| 702 | DWORDLONG dwlConditionMask) |
| 703 | { |
| 704 | OSVERSIONINFOEXW verW; |
| 705 | |
| 706 | verW.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); |
| 707 | verW.dwMajorVersion = lpVersionInfo->dwMajorVersion; |
| 708 | verW.dwMinorVersion = lpVersionInfo->dwMinorVersion; |
| 709 | verW.dwBuildNumber = lpVersionInfo->dwBuildNumber; |
| 710 | verW.dwPlatformId = lpVersionInfo->dwPlatformId; |
| 711 | verW.wServicePackMajor = lpVersionInfo->wServicePackMajor; |
| 712 | verW.wServicePackMinor = lpVersionInfo->wServicePackMinor; |
| 713 | verW.wSuiteMask = lpVersionInfo->wSuiteMask; |
| 714 | verW.wProductType = lpVersionInfo->wProductType; |
| 715 | verW.wReserved = lpVersionInfo->wReserved; |
| 716 | |
| 717 | return VerifyVersionInfoW(&verW, dwTypeMask, dwlConditionMask); |
| 718 | } |
| 719 | |
Juergen Schmied | c5d3053 | 2002-05-09 19:36:28 +0000 | [diff] [blame] | 720 | |
| 721 | /****************************************************************************** |
| 722 | * VerifyVersionInfoW (KERNEL32.@) |
| 723 | */ |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 724 | BOOL WINAPI VerifyVersionInfoW( LPOSVERSIONINFOEXW lpVersionInfo, DWORD dwTypeMask, |
Juergen Schmied | c5d3053 | 2002-05-09 19:36:28 +0000 | [diff] [blame] | 725 | DWORDLONG dwlConditionMask) |
| 726 | { |
Vincent Béron | 9d9cf72 | 2002-05-24 21:13:45 +0000 | [diff] [blame] | 727 | OSVERSIONINFOEXW ver; |
| 728 | BOOL res, error_set; |
| 729 | |
| 730 | FIXME("(%p,%lu,%llx): Not all cases correctly implemented yet\n", lpVersionInfo, dwTypeMask, dwlConditionMask); |
| 731 | /* FIXME: |
| 732 | - Check the following special case on Windows (various versions): |
| 733 | o lp->wSuiteMask == 0 and ver.wSuiteMask != 0 and VER_AND/VER_OR |
| 734 | o lp->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXW) |
| 735 | - MSDN talks about some tests being impossible. Check what really happens. |
| 736 | */ |
| 737 | |
| 738 | ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); |
| 739 | if(!GetVersionExW((LPOSVERSIONINFOW) &ver)) |
| 740 | return FALSE; |
| 741 | |
| 742 | res = TRUE; |
| 743 | error_set = FALSE; |
| 744 | if(!(dwTypeMask && dwlConditionMask)) { |
| 745 | res = FALSE; |
| 746 | SetLastError(ERROR_BAD_ARGUMENTS); |
| 747 | error_set = TRUE; |
| 748 | } |
| 749 | if(dwTypeMask & VER_PRODUCT_TYPE) |
| 750 | switch(dwlConditionMask >> 7*3 & 0x07) { |
| 751 | case VER_EQUAL: |
| 752 | if(ver.wProductType != lpVersionInfo->wProductType) |
| 753 | res = FALSE; |
| 754 | break; |
| 755 | case VER_GREATER: |
| 756 | if(ver.wProductType <= lpVersionInfo->wProductType) |
| 757 | res = FALSE; |
| 758 | break; |
| 759 | case VER_GREATER_EQUAL: |
| 760 | if(ver.wProductType < lpVersionInfo->wProductType) |
| 761 | res = FALSE; |
| 762 | break; |
| 763 | case VER_LESS: |
| 764 | if(ver.wProductType >= lpVersionInfo->wProductType) |
| 765 | res = FALSE; |
| 766 | break; |
| 767 | case VER_LESS_EQUAL: |
| 768 | if(ver.wProductType > lpVersionInfo->wProductType) |
| 769 | res = FALSE; |
| 770 | break; |
| 771 | default: |
| 772 | res = FALSE; |
| 773 | SetLastError(ERROR_BAD_ARGUMENTS); |
| 774 | error_set = TRUE; |
| 775 | } |
| 776 | if(dwTypeMask & VER_SUITENAME && res) |
| 777 | switch(dwlConditionMask >> 6*3 & 0x07) { |
| 778 | case VER_AND: |
| 779 | if((lpVersionInfo->wSuiteMask & ver.wSuiteMask) != lpVersionInfo->wSuiteMask) |
| 780 | res = FALSE; |
| 781 | break; |
| 782 | case VER_OR: |
| 783 | if(!(lpVersionInfo->wSuiteMask & ver.wSuiteMask) && lpVersionInfo->wSuiteMask) |
| 784 | res = FALSE; |
| 785 | break; |
| 786 | default: |
| 787 | res = FALSE; |
| 788 | SetLastError(ERROR_BAD_ARGUMENTS); |
| 789 | error_set = TRUE; |
| 790 | } |
| 791 | if(dwTypeMask & VER_PLATFORMID && res) |
| 792 | switch(dwlConditionMask >> 3*3 & 0x07) { |
| 793 | case VER_EQUAL: |
| 794 | if(ver.dwPlatformId != lpVersionInfo->dwPlatformId) |
| 795 | res = FALSE; |
| 796 | break; |
| 797 | case VER_GREATER: |
| 798 | if(ver.dwPlatformId <= lpVersionInfo->dwPlatformId) |
| 799 | res = FALSE; |
| 800 | break; |
| 801 | case VER_GREATER_EQUAL: |
| 802 | if(ver.dwPlatformId < lpVersionInfo->dwPlatformId) |
| 803 | res = FALSE; |
| 804 | break; |
| 805 | case VER_LESS: |
| 806 | if(ver.dwPlatformId >= lpVersionInfo->dwPlatformId) |
| 807 | res = FALSE; |
| 808 | break; |
| 809 | case VER_LESS_EQUAL: |
| 810 | if(ver.dwPlatformId > lpVersionInfo->dwPlatformId) |
| 811 | res = FALSE; |
| 812 | break; |
| 813 | default: |
| 814 | res = FALSE; |
| 815 | SetLastError(ERROR_BAD_ARGUMENTS); |
| 816 | error_set = TRUE; |
| 817 | } |
| 818 | if(dwTypeMask & VER_BUILDNUMBER && res) |
| 819 | switch(dwlConditionMask >> 2*3 & 0x07) { |
| 820 | case VER_EQUAL: |
| 821 | if(ver.dwBuildNumber != lpVersionInfo->dwBuildNumber) |
| 822 | res = FALSE; |
| 823 | break; |
| 824 | case VER_GREATER: |
| 825 | if(ver.dwBuildNumber <= lpVersionInfo->dwBuildNumber) |
| 826 | res = FALSE; |
| 827 | break; |
| 828 | case VER_GREATER_EQUAL: |
| 829 | if(ver.dwBuildNumber < lpVersionInfo->dwBuildNumber) |
| 830 | res = FALSE; |
| 831 | break; |
| 832 | case VER_LESS: |
| 833 | if(ver.dwBuildNumber >= lpVersionInfo->dwBuildNumber) |
| 834 | res = FALSE; |
| 835 | break; |
| 836 | case VER_LESS_EQUAL: |
| 837 | if(ver.dwBuildNumber > lpVersionInfo->dwBuildNumber) |
| 838 | res = FALSE; |
| 839 | break; |
| 840 | default: |
| 841 | res = FALSE; |
| 842 | SetLastError(ERROR_BAD_ARGUMENTS); |
| 843 | error_set = TRUE; |
| 844 | } |
| 845 | if(dwTypeMask & VER_MAJORVERSION && res) |
| 846 | switch(dwlConditionMask >> 1*3 & 0x07) { |
| 847 | case VER_EQUAL: |
| 848 | if(ver.dwMajorVersion != lpVersionInfo->dwMajorVersion) |
| 849 | res = FALSE; |
| 850 | break; |
| 851 | case VER_GREATER: |
| 852 | if(ver.dwMajorVersion <= lpVersionInfo->dwMajorVersion) |
| 853 | res = FALSE; |
| 854 | break; |
| 855 | case VER_GREATER_EQUAL: |
| 856 | if(ver.dwMajorVersion < lpVersionInfo->dwMajorVersion) |
| 857 | res = FALSE; |
| 858 | break; |
| 859 | case VER_LESS: |
| 860 | if(ver.dwMajorVersion >= lpVersionInfo->dwMajorVersion) |
| 861 | res = FALSE; |
| 862 | break; |
| 863 | case VER_LESS_EQUAL: |
| 864 | if(ver.dwMajorVersion > lpVersionInfo->dwMajorVersion) |
| 865 | res = FALSE; |
| 866 | break; |
| 867 | default: |
| 868 | res = FALSE; |
| 869 | SetLastError(ERROR_BAD_ARGUMENTS); |
| 870 | error_set = TRUE; |
| 871 | } |
| 872 | if(dwTypeMask & VER_MINORVERSION && res) |
| 873 | switch(dwlConditionMask >> 0*3 & 0x07) { |
| 874 | case VER_EQUAL: |
| 875 | if(ver.dwMinorVersion != lpVersionInfo->dwMinorVersion) |
| 876 | res = FALSE; |
| 877 | break; |
| 878 | case VER_GREATER: |
| 879 | if(ver.dwMinorVersion <= lpVersionInfo->dwMinorVersion) |
| 880 | res = FALSE; |
| 881 | break; |
| 882 | case VER_GREATER_EQUAL: |
| 883 | if(ver.dwMinorVersion < lpVersionInfo->dwMinorVersion) |
| 884 | res = FALSE; |
| 885 | break; |
| 886 | case VER_LESS: |
| 887 | if(ver.dwMinorVersion >= lpVersionInfo->dwMinorVersion) |
| 888 | res = FALSE; |
| 889 | break; |
| 890 | case VER_LESS_EQUAL: |
| 891 | if(ver.dwMinorVersion > lpVersionInfo->dwMinorVersion) |
| 892 | res = FALSE; |
| 893 | break; |
| 894 | default: |
| 895 | res = FALSE; |
| 896 | SetLastError(ERROR_BAD_ARGUMENTS); |
| 897 | error_set = TRUE; |
| 898 | } |
| 899 | if(dwTypeMask & VER_SERVICEPACKMAJOR && res) |
| 900 | switch(dwlConditionMask >> 5*3 & 0x07) { |
| 901 | case VER_EQUAL: |
| 902 | if(ver.wServicePackMajor != lpVersionInfo->wServicePackMajor) |
| 903 | res = FALSE; |
| 904 | break; |
| 905 | case VER_GREATER: |
| 906 | if(ver.wServicePackMajor <= lpVersionInfo->wServicePackMajor) |
| 907 | res = FALSE; |
| 908 | break; |
| 909 | case VER_GREATER_EQUAL: |
| 910 | if(ver.wServicePackMajor < lpVersionInfo->wServicePackMajor) |
| 911 | res = FALSE; |
| 912 | break; |
| 913 | case VER_LESS: |
| 914 | if(ver.wServicePackMajor >= lpVersionInfo->wServicePackMajor) |
| 915 | res = FALSE; |
| 916 | break; |
| 917 | case VER_LESS_EQUAL: |
| 918 | if(ver.wServicePackMajor > lpVersionInfo->wServicePackMajor) |
| 919 | res = FALSE; |
| 920 | break; |
| 921 | default: |
| 922 | res = FALSE; |
| 923 | SetLastError(ERROR_BAD_ARGUMENTS); |
| 924 | error_set = TRUE; |
| 925 | } |
| 926 | if(dwTypeMask & VER_SERVICEPACKMINOR && res) |
| 927 | switch(dwlConditionMask >> 4*3 & 0x07) { |
| 928 | case VER_EQUAL: |
| 929 | if(ver.wServicePackMinor != lpVersionInfo->wServicePackMinor) |
| 930 | res = FALSE; |
| 931 | break; |
| 932 | case VER_GREATER: |
| 933 | if(ver.wServicePackMinor <= lpVersionInfo->wServicePackMinor) |
| 934 | res = FALSE; |
| 935 | break; |
| 936 | case VER_GREATER_EQUAL: |
| 937 | if(ver.wServicePackMinor < lpVersionInfo->wServicePackMinor) |
| 938 | res = FALSE; |
| 939 | break; |
| 940 | case VER_LESS: |
| 941 | if(ver.wServicePackMinor >= lpVersionInfo->wServicePackMinor) |
| 942 | res = FALSE; |
| 943 | break; |
| 944 | case VER_LESS_EQUAL: |
| 945 | if(ver.wServicePackMinor > lpVersionInfo->wServicePackMinor) |
| 946 | res = FALSE; |
| 947 | break; |
| 948 | default: |
| 949 | res = FALSE; |
| 950 | SetLastError(ERROR_BAD_ARGUMENTS); |
| 951 | error_set = TRUE; |
| 952 | } |
| 953 | |
| 954 | if(!(res || error_set)) |
| 955 | SetLastError(ERROR_OLD_WIN_VERSION); |
| 956 | return res; |
Juergen Schmied | c5d3053 | 2002-05-09 19:36:28 +0000 | [diff] [blame] | 957 | } |
| 958 | |
| 959 | |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 960 | /*********************************************************************** |
| 961 | * GetWinFlags (KERNEL.132) |
| 962 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 963 | DWORD WINAPI GetWinFlags16(void) |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 964 | { |
| 965 | static const long cpuflags[5] = |
| 966 | { WF_CPU086, WF_CPU186, WF_CPU286, WF_CPU386, WF_CPU486 }; |
| 967 | SYSTEM_INFO si; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 968 | OSVERSIONINFOA ovi; |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 969 | DWORD result; |
| 970 | |
| 971 | GetSystemInfo(&si); |
| 972 | |
| 973 | /* There doesn't seem to be any Pentium flag. */ |
Francois Gouget | 6d77d3a | 2000-03-25 21:44:35 +0000 | [diff] [blame] | 974 | result = cpuflags[min(si.wProcessorLevel, 4)] | WF_ENHANCED | WF_PMODE | WF_80x87 | WF_PAGING; |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 975 | if (si.wProcessorLevel >= 4) result |= WF_HASCPUID; |
| 976 | ovi.dwOSVersionInfoSize = sizeof(ovi); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 977 | GetVersionExA(&ovi); |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 978 | if (ovi.dwPlatformId == VER_PLATFORM_WIN32_NT) |
| 979 | result |= WF_WIN32WOW; /* undocumented WF_WINNT */ |
| 980 | return result; |
| 981 | } |
| 982 | |
| 983 | |
Francois Gouget | 5686dc0 | 2001-10-08 22:30:34 +0000 | [diff] [blame] | 984 | #if 0 |
| 985 | /* Not used at this time. This is here for documentation only */ |
| 986 | |
| 987 | /* WINDEBUGINFO flags values */ |
| 988 | #define WDI_OPTIONS 0x0001 |
| 989 | #define WDI_FILTER 0x0002 |
| 990 | #define WDI_ALLOCBREAK 0x0004 |
| 991 | |
| 992 | /* dwOptions values */ |
| 993 | #define DBO_CHECKHEAP 0x0001 |
| 994 | #define DBO_BUFFERFILL 0x0004 |
| 995 | #define DBO_DISABLEGPTRAPPING 0x0010 |
| 996 | #define DBO_CHECKFREE 0x0020 |
| 997 | |
| 998 | #define DBO_SILENT 0x8000 |
| 999 | |
| 1000 | #define DBO_TRACEBREAK 0x2000 |
| 1001 | #define DBO_WARNINGBREAK 0x1000 |
| 1002 | #define DBO_NOERRORBREAK 0x0800 |
| 1003 | #define DBO_NOFATALBREAK 0x0400 |
| 1004 | #define DBO_INT3BREAK 0x0100 |
| 1005 | |
| 1006 | /* DebugOutput flags values */ |
| 1007 | #define DBF_TRACE 0x0000 |
| 1008 | #define DBF_WARNING 0x4000 |
| 1009 | #define DBF_ERROR 0x8000 |
| 1010 | #define DBF_FATAL 0xc000 |
| 1011 | |
| 1012 | /* dwFilter values */ |
| 1013 | #define DBF_KERNEL 0x1000 |
| 1014 | #define DBF_KRN_MEMMAN 0x0001 |
| 1015 | #define DBF_KRN_LOADMODULE 0x0002 |
| 1016 | #define DBF_KRN_SEGMENTLOAD 0x0004 |
| 1017 | #define DBF_USER 0x0800 |
| 1018 | #define DBF_GDI 0x0400 |
| 1019 | #define DBF_MMSYSTEM 0x0040 |
| 1020 | #define DBF_PENWIN 0x0020 |
| 1021 | #define DBF_APPLICATION 0x0008 |
| 1022 | #define DBF_DRIVER 0x0010 |
| 1023 | |
| 1024 | #endif /* NOLOGERROR */ |
| 1025 | |
| 1026 | |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 1027 | /*********************************************************************** |
| 1028 | * GetWinDebugInfo (KERNEL.355) |
| 1029 | */ |
Francois Gouget | 5686dc0 | 2001-10-08 22:30:34 +0000 | [diff] [blame] | 1030 | BOOL16 WINAPI GetWinDebugInfo16(WINDEBUGINFO16 *lpwdi, UINT16 flags) |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 1031 | { |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1032 | FIXME("(%8lx,%d): stub returning 0\n", |
Alexandre Julliard | 54c2711 | 1998-03-29 19:44:57 +0000 | [diff] [blame] | 1033 | (unsigned long)lpwdi, flags); |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 1034 | /* 0 means not in debugging mode/version */ |
| 1035 | /* Can this type of debugging be used in wine ? */ |
| 1036 | /* Constants: WDI_OPTIONS WDI_FILTER WDI_ALLOCBREAK */ |
| 1037 | return 0; |
| 1038 | } |
| 1039 | |
| 1040 | |
| 1041 | /*********************************************************************** |
| 1042 | * SetWinDebugInfo (KERNEL.356) |
| 1043 | */ |
Francois Gouget | 5686dc0 | 2001-10-08 22:30:34 +0000 | [diff] [blame] | 1044 | BOOL16 WINAPI SetWinDebugInfo16(WINDEBUGINFO16 *lpwdi) |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 1045 | { |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 1046 | FIXME("(%8lx): stub returning 0\n", (unsigned long)lpwdi); |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 1047 | /* 0 means not in debugging mode/version */ |
| 1048 | /* Can this type of debugging be used in wine ? */ |
| 1049 | /* Constants: WDI_OPTIONS WDI_FILTER WDI_ALLOCBREAK */ |
| 1050 | return 0; |
| 1051 | } |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1052 | |
| 1053 | |
| 1054 | /*********************************************************************** |
Patrik Stridvall | 01d5e5b | 2001-07-02 19:59:40 +0000 | [diff] [blame] | 1055 | * K329 (KERNEL.329) |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1056 | * |
| 1057 | * TODO: |
| 1058 | * Should fill lpBuffer only if DBO_BUFFERFILL has been set by SetWinDebugInfo() |
| 1059 | */ |
| 1060 | void WINAPI DebugFillBuffer(LPSTR lpBuffer, WORD wBytes) |
| 1061 | { |
| 1062 | memset(lpBuffer, DBGFILL_BUFFER, wBytes); |
| 1063 | } |
| 1064 | |
| 1065 | /*********************************************************************** |
| 1066 | * DiagQuery (KERNEL.339) |
| 1067 | * |
| 1068 | * returns TRUE if Win called with "/b" (bootlog.txt) |
| 1069 | */ |
Patrik Stridvall | 57bf450 | 2002-08-26 21:53:24 +0000 | [diff] [blame] | 1070 | BOOL16 WINAPI DiagQuery16(void) |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1071 | { |
| 1072 | /* perhaps implement a Wine "/b" command line flag sometime ? */ |
| 1073 | return FALSE; |
| 1074 | } |
| 1075 | |
| 1076 | /*********************************************************************** |
| 1077 | * DiagOutput (KERNEL.340) |
| 1078 | * |
| 1079 | * writes a debug string into <windir>\bootlog.txt |
| 1080 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1081 | void WINAPI DiagOutput16(LPCSTR str) |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1082 | { |
Alexandre Julliard | 54c2711 | 1998-03-29 19:44:57 +0000 | [diff] [blame] | 1083 | /* FIXME */ |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 1084 | DPRINTF("DIAGOUTPUT:%s\n", debugstr_a(str)); |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1085 | } |