1 /*
2  * Unit test suite for version functions
3  *
4  * Copyright 2006 Robert Shearman
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 /* Needed for PRODUCT_* defines and GetProductInfo() */
22 #ifndef __REACTOS__
23 #define _WIN32_WINNT 0x0600
24 #endif
25 
26 #include "wine/test.h"
27 #include "winbase.h"
28 #include "winternl.h"
29 
30 static BOOL (WINAPI * pGetProductInfo)(DWORD, DWORD, DWORD, DWORD, DWORD *);
31 static NTSTATUS (WINAPI * pRtlGetVersion)(RTL_OSVERSIONINFOEXW *);
32 
33 #define GET_PROC(func)                                     \
34     p##func = (void *)GetProcAddress(hmod, #func);
35 
36 static void init_function_pointers(void)
37 {
38     HMODULE hmod;
39 
40     hmod = GetModuleHandleA("kernel32.dll");
41 
42     GET_PROC(GetProductInfo);
43 
44     hmod = GetModuleHandleA("ntdll.dll");
45 
46     GET_PROC(RtlGetVersion);
47 }
48 
49 static void test_GetProductInfo(void)
50 {
51     DWORD product;
52     DWORD res;
53     DWORD table[] = {9,8,7,6,
54                      7,0,0,0,
55                      6,2,0,0,
56                      6,1,2,0,
57                      6,1,1,0,
58                      6,1,0,2,
59                      6,1,0,0,
60                      6,0,3,0,
61                      6,0,2,0,
62                      6,0,1,5,
63                      6,0,1,0,
64                      6,0,0,0,
65                      5,3,0,0,
66                      5,2,0,0,
67                      5,1,0,0,
68                      5,0,0,0,
69                      0};
70 
71     DWORD *entry = table;
72 
73     if (!pGetProductInfo)
74     {
75         /* Not present before Vista */
76         win_skip("GetProductInfo() not available\n");
77         return;
78     }
79 
80     while (*entry)
81     {
82         /* SetLastError() / GetLastError(): value is untouched */
83         product = 0xdeadbeef;
84         SetLastError(0xdeadbeef);
85         res = pGetProductInfo(entry[0], entry[1], entry[2], entry[3], &product);
86 
87         if (entry[0] >= 6)
88             ok(res && (product > PRODUCT_UNDEFINED) && (product <= PRODUCT_ENTERPRISE_S_N_EVALUATION),
89                "got %d and 0x%x (expected TRUE and a valid PRODUCT_* value)\n", res, product);
90         else
91             ok(!res && !product && (GetLastError() == 0xdeadbeef),
92                "got %d and 0x%x with 0x%x (expected FALSE and PRODUCT_UNDEFINED with LastError untouched)\n",
93                res, product, GetLastError());
94 
95         entry+= 4;
96     }
97 
98     /* NULL pointer is not a problem */
99     SetLastError(0xdeadbeef);
100     res = pGetProductInfo(6, 1, 0, 0, NULL);
101     ok( (!res) && (GetLastError() == 0xdeadbeef),
102         "got %d with 0x%x (expected FALSE with LastError untouched\n", res, GetLastError());
103 }
104 
105 static void test_GetVersionEx(void)
106 {
107     OSVERSIONINFOA infoA;
108     OSVERSIONINFOEXA infoExA;
109     BOOL ret;
110 
111     if (0)
112     {
113         /* Silently crashes on XP */
114         GetVersionExA(NULL);
115     }
116 
117     SetLastError(0xdeadbeef);
118     memset(&infoA,0,sizeof infoA);
119     ret = GetVersionExA(&infoA);
120     ok(!ret, "Expected GetVersionExA to fail\n");
121     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
122         GetLastError() == 0xdeadbeef /* Win9x */,
123         "Expected ERROR_INSUFFICIENT_BUFFER or 0xdeadbeef (Win9x), got %d\n",
124         GetLastError());
125 
126     SetLastError(0xdeadbeef);
127     infoA.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA) / 2;
128     ret = GetVersionExA(&infoA);
129     ok(!ret, "Expected GetVersionExA to fail\n");
130     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
131         GetLastError() == 0xdeadbeef /* Win9x */,
132         "Expected ERROR_INSUFFICIENT_BUFFER or 0xdeadbeef (Win9x), got %d\n",
133         GetLastError());
134 
135     SetLastError(0xdeadbeef);
136     infoA.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA) * 2;
137     ret = GetVersionExA(&infoA);
138     ok(!ret, "Expected GetVersionExA to fail\n");
139     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
140         GetLastError() == 0xdeadbeef /* Win9x */,
141         "Expected ERROR_INSUFFICIENT_BUFFER or 0xdeadbeef (Win9x), got %d\n",
142         GetLastError());
143 
144     SetLastError(0xdeadbeef);
145     infoA.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
146     ret = GetVersionExA(&infoA);
147     ok(ret, "Expected GetVersionExA to succeed\n");
148     ok(GetLastError() == 0xdeadbeef,
149         "Expected 0xdeadbeef, got %d\n", GetLastError());
150 
151     SetLastError(0xdeadbeef);
152     infoExA.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
153     ret = GetVersionExA((OSVERSIONINFOA *)&infoExA);
154     ok(ret, "GetVersionExA failed.\n");
155 
156     if (!infoExA.wServicePackMajor && !infoExA.wServicePackMinor)
157         ok(!infoExA.szCSDVersion[0], "got '%s'\n", infoExA.szCSDVersion);
158 }
159 
160 static void test_VerifyVersionInfo(void)
161 {
162     enum srcversion_mode
163     {
164         SRCVERSION_ZERO         = 0,
165         SRCVERSION_CURRENT      = 1,
166         SRCVERSION_INC_MINOR    = 2,
167         SRCVERSION_INC_SP_MINOR = 3,
168         SRCVERSION_INC_SP_MAJOR = 4,
169         SRCVERSION_DEC_SP_MAJOR = 5,
170         SRCVERSION_DEC_MAJOR    = 6,
171         SRCVERSION_INC_BUILD    = 7,
172         SRCVERSION_REQUIRES_SP  = 0x1000,
173     };
174 
175     struct verify_version_test
176     {
177         DWORD verifymask; /* Type mask for VerifyVersionInfo() */
178         DWORD srcinfo;    /* The way current version info is modified. */
179         DWORD err;        /* Error code on failure, 0 on success. */
180 
181         DWORD typemask1;
182         DWORD condition1;
183         DWORD typemask2;
184         DWORD condition2;
185         DWORD typemask3;
186         DWORD condition3;
187         DWORD typemask4;
188         DWORD condition4;
189 
190         BOOL todo;
191     } verify_version_tests[] =
192     {
193         {
194             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
195             SRCVERSION_INC_MINOR,
196             0,
197 
198             VER_MAJORVERSION, VER_EQUAL,
199             VER_MINORVERSION, VER_LESS,
200         },
201         {
202             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
203             SRCVERSION_INC_MINOR,
204             ERROR_OLD_WIN_VERSION,
205 
206             VER_MAJORVERSION, VER_GREATER_EQUAL,
207             VER_MINORVERSION, VER_LESS,
208         },
209         {
210             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
211             SRCVERSION_CURRENT,
212             0,
213 
214             VER_MAJORVERSION, VER_GREATER_EQUAL,
215             VER_MINORVERSION, VER_LESS,
216         },
217         {
218             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
219             SRCVERSION_CURRENT,
220             0,
221 
222             VER_MAJORVERSION, VER_GREATER_EQUAL,
223             VER_MINORVERSION, VER_AND,
224         },
225         {
226             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
227             SRCVERSION_INC_MINOR,
228             0,
229 
230             VER_MAJORVERSION, VER_LESS_EQUAL,
231             VER_MINORVERSION, VER_LESS,
232         },
233         {
234             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
235             SRCVERSION_INC_MINOR,
236             ERROR_OLD_WIN_VERSION,
237 
238             VER_MAJORVERSION, VER_AND,
239             VER_MINORVERSION, VER_LESS,
240         },
241         {
242             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
243             SRCVERSION_INC_MINOR,
244             ERROR_OLD_WIN_VERSION,
245 
246             VER_MAJORVERSION, VER_OR,
247             VER_MINORVERSION, VER_LESS,
248         },
249         {
250             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
251             SRCVERSION_INC_SP_MINOR,
252             ERROR_OLD_WIN_VERSION,
253 
254             VER_MINORVERSION, VER_EQUAL,
255             VER_SERVICEPACKMINOR, VER_LESS,
256         },
257         {
258             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
259             SRCVERSION_INC_SP_MINOR,
260             ERROR_OLD_WIN_VERSION,
261 
262             VER_MAJORVERSION, VER_EQUAL,
263             VER_SERVICEPACKMINOR, VER_LESS,
264         },
265         {
266             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
267             SRCVERSION_INC_SP_MAJOR,
268             ERROR_OLD_WIN_VERSION,
269 
270             VER_MAJORVERSION, VER_EQUAL,
271             VER_SERVICEPACKMAJOR, VER_EQUAL,
272         },
273         {
274             VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
275             SRCVERSION_INC_SP_MINOR,
276             0,
277 
278             VER_SERVICEPACKMAJOR, VER_EQUAL,
279             VER_SERVICEPACKMINOR, VER_LESS,
280         },
281         {
282             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
283             SRCVERSION_INC_SP_MINOR,
284             ERROR_OLD_WIN_VERSION,
285 
286             VER_SERVICEPACKMAJOR, VER_EQUAL,
287             VER_SERVICEPACKMINOR, VER_LESS,
288         },
289         {
290             VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
291             SRCVERSION_INC_SP_MINOR,
292             0,
293 
294             VER_MINORVERSION, VER_EQUAL,
295             VER_SERVICEPACKMAJOR, VER_EQUAL,
296             VER_SERVICEPACKMINOR, VER_LESS,
297         },
298         {
299             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
300             SRCVERSION_INC_SP_MINOR,
301             ERROR_OLD_WIN_VERSION,
302 
303             VER_MINORVERSION, VER_EQUAL,
304             VER_SERVICEPACKMAJOR, VER_EQUAL,
305             VER_SERVICEPACKMINOR, VER_LESS,
306         },
307         {
308             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
309             SRCVERSION_INC_SP_MINOR,
310             0,
311 
312             VER_MAJORVERSION, VER_EQUAL,
313             VER_MINORVERSION, VER_EQUAL,
314             VER_SERVICEPACKMAJOR, VER_EQUAL,
315             VER_SERVICEPACKMINOR, VER_LESS,
316         },
317         {
318             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
319             SRCVERSION_INC_SP_MINOR,
320             ERROR_OLD_WIN_VERSION,
321 
322             VER_MAJORVERSION, VER_EQUAL,
323             VER_MINORVERSION, VER_GREATER_EQUAL,
324             VER_SERVICEPACKMAJOR, VER_EQUAL,
325             VER_SERVICEPACKMINOR, VER_LESS,
326         },
327         {
328             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
329             SRCVERSION_INC_SP_MAJOR,
330             0,
331 
332             VER_MAJORVERSION, VER_LESS_EQUAL,
333             VER_SERVICEPACKMAJOR, VER_GREATER,
334         },
335         {
336             VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
337             SRCVERSION_INC_SP_MAJOR,
338             ERROR_OLD_WIN_VERSION,
339 
340             VER_MAJORVERSION, VER_EQUAL,
341             VER_SERVICEPACKMAJOR, VER_LESS,
342         },
343         {
344             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
345             SRCVERSION_INC_SP_MAJOR,
346             ERROR_OLD_WIN_VERSION,
347 
348             VER_MINORVERSION, VER_EQUAL,
349             VER_SERVICEPACKMAJOR, VER_LESS,
350         },
351         {
352             VER_MAJORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
353             SRCVERSION_INC_SP_MAJOR,
354             0,
355 
356             VER_MAJORVERSION, VER_EQUAL,
357             VER_SERVICEPACKMAJOR, VER_LESS,
358         },
359         {
360             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
361             SRCVERSION_INC_SP_MAJOR,
362             ERROR_OLD_WIN_VERSION,
363 
364             VER_MAJORVERSION, VER_EQUAL,
365             VER_SERVICEPACKMAJOR, VER_LESS,
366         },
367         {
368             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
369             SRCVERSION_INC_SP_MAJOR,
370             0,
371 
372             VER_MAJORVERSION, VER_EQUAL,
373             VER_MINORVERSION, VER_EQUAL,
374             VER_SERVICEPACKMAJOR, VER_LESS,
375         },
376         {
377             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
378             SRCVERSION_INC_SP_MAJOR,
379             ERROR_OLD_WIN_VERSION,
380 
381             VER_MAJORVERSION, VER_GREATER_EQUAL,
382             VER_SERVICEPACKMAJOR, VER_LESS,
383         },
384         {
385             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
386             SRCVERSION_DEC_MAJOR,
387             0,
388 
389             VER_MAJORVERSION, VER_GREATER_EQUAL,
390             VER_SERVICEPACKMAJOR, VER_LESS,
391         },
392         {
393             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
394             SRCVERSION_CURRENT,
395             0,
396 
397             VER_MAJORVERSION, VER_GREATER_EQUAL,
398             VER_SERVICEPACKMAJOR, VER_LESS,
399         },
400         {
401             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
402             SRCVERSION_INC_SP_MAJOR,
403             ERROR_OLD_WIN_VERSION,
404 
405             VER_MAJORVERSION, VER_GREATER_EQUAL,
406             VER_MINORVERSION, VER_EQUAL,
407             VER_SERVICEPACKMAJOR, VER_LESS,
408         },
409         {
410             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
411             SRCVERSION_INC_SP_MAJOR,
412             ERROR_OLD_WIN_VERSION,
413 
414             VER_MAJORVERSION, VER_GREATER_EQUAL,
415             VER_MINORVERSION, VER_GREATER_EQUAL,
416             VER_SERVICEPACKMAJOR, VER_LESS_EQUAL,
417         },
418         {
419             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
420             SRCVERSION_INC_SP_MAJOR,
421             ERROR_OLD_WIN_VERSION,
422 
423             VER_MAJORVERSION, VER_GREATER_EQUAL,
424             VER_SERVICEPACKMAJOR, VER_AND,
425         },
426         {
427             VER_MAJORVERSION | VER_MINORVERSION,
428             SRCVERSION_ZERO,
429             0,
430 
431             VER_MAJORVERSION, VER_GREATER_EQUAL,
432         },
433         {
434             VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER,
435             SRCVERSION_ZERO,
436             ERROR_OLD_WIN_VERSION,
437 
438             VER_MAJORVERSION, VER_GREATER_EQUAL,
439         },
440         {
441             VER_SUITENAME,
442             SRCVERSION_ZERO,
443             0,
444 
445             VER_SUITENAME, VER_AND,
446         },
447         {
448             VER_SUITENAME,
449             SRCVERSION_ZERO,
450             0,
451 
452             VER_SUITENAME, VER_OR,
453         },
454         {
455             VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
456             SRCVERSION_INC_SP_MINOR,
457             ERROR_OLD_WIN_VERSION,
458 
459             VER_MINORVERSION, VER_GREATER_EQUAL,
460         },
461         {
462             VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
463             SRCVERSION_INC_SP_MAJOR,
464             0,
465 
466             VER_MINORVERSION, VER_LESS,
467         },
468         {
469             VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
470             SRCVERSION_INC_SP_MAJOR,
471             0,
472 
473             VER_MINORVERSION, VER_LESS_EQUAL,
474         },
475         {
476             VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
477             SRCVERSION_INC_SP_MAJOR,
478             ERROR_OLD_WIN_VERSION,
479 
480             VER_MINORVERSION, VER_EQUAL,
481         },
482         {
483             VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
484             SRCVERSION_INC_SP_MAJOR,
485             ERROR_OLD_WIN_VERSION,
486 
487             VER_MINORVERSION, VER_GREATER_EQUAL,
488         },
489         {
490             VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
491             SRCVERSION_INC_MINOR,
492             ERROR_OLD_WIN_VERSION,
493 
494             VER_MINORVERSION, VER_GREATER_EQUAL,
495         },
496         {
497             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
498             SRCVERSION_INC_MINOR,
499             ERROR_OLD_WIN_VERSION,
500 
501             VER_MINORVERSION, VER_GREATER_EQUAL,
502         },
503         {
504             VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
505             SRCVERSION_CURRENT,
506             0,
507 
508             VER_MINORVERSION, VER_GREATER_EQUAL,
509         },
510         {
511             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
512             SRCVERSION_INC_BUILD,
513             ERROR_OLD_WIN_VERSION,
514 
515             VER_MINORVERSION, VER_GREATER_EQUAL,
516         },
517         {
518             VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
519             SRCVERSION_INC_BUILD,
520             0,
521 
522             VER_MINORVERSION, VER_GREATER_EQUAL,
523         },
524         {
525             VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
526             SRCVERSION_DEC_SP_MAJOR | SRCVERSION_REQUIRES_SP,
527             0,
528 
529             VER_MINORVERSION, VER_GREATER,
530         },
531         {
532             VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
533             SRCVERSION_DEC_SP_MAJOR | SRCVERSION_REQUIRES_SP,
534             0,
535 
536             VER_MINORVERSION, VER_GREATER_EQUAL,
537         },
538         {
539             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
540             SRCVERSION_DEC_SP_MAJOR | SRCVERSION_REQUIRES_SP,
541             ERROR_OLD_WIN_VERSION,
542 
543             VER_MAJORVERSION, VER_EQUAL,
544             VER_SERVICEPACKMAJOR, VER_GREATER,
545         },
546         {
547             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
548             SRCVERSION_DEC_SP_MAJOR | SRCVERSION_REQUIRES_SP,
549             0,
550 
551             VER_MAJORVERSION, VER_GREATER_EQUAL,
552             VER_MINORVERSION, VER_EQUAL,
553             VER_SERVICEPACKMAJOR, VER_GREATER,
554         },
555         {
556             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
557             SRCVERSION_DEC_SP_MAJOR | SRCVERSION_REQUIRES_SP,
558             0,
559 
560             VER_MAJORVERSION, VER_GREATER_EQUAL,
561             VER_MINORVERSION, VER_LESS_EQUAL,
562             VER_SERVICEPACKMAJOR, VER_GREATER,
563         },
564         {
565             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
566             SRCVERSION_DEC_SP_MAJOR | SRCVERSION_REQUIRES_SP,
567             0,
568 
569             VER_MAJORVERSION, VER_GREATER_EQUAL,
570             VER_MINORVERSION, VER_AND,
571             VER_SERVICEPACKMAJOR, VER_GREATER,
572         },
573         {
574             VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
575             SRCVERSION_DEC_SP_MAJOR | SRCVERSION_REQUIRES_SP,
576             ERROR_OLD_WIN_VERSION,
577 
578             VER_SERVICEPACKMAJOR, VER_GREATER,
579             VER_SERVICEPACKMINOR, VER_EQUAL,
580         },
581     };
582 
583     OSVERSIONINFOEXA info;
584     DWORD servicepack;
585     unsigned int i;
586     BOOL ret;
587 
588     /* Before we start doing some tests we should check what the version of
589      * the ServicePack is. Tests on a box with no ServicePack will fail otherwise.
590      */
591     info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
592     GetVersionExA((OSVERSIONINFOA *)&info);
593     servicepack = info.wServicePackMajor;
594     if (servicepack == 0)
595         skip("There is no ServicePack on this system. Some tests will be skipped.\n");
596 
597     /* Win8.1+ returns Win8 version in GetVersionEx when there's no app manifest targeting 8.1 */
598     if (info.dwMajorVersion == 6 && info.dwMinorVersion == 2)
599     {
600         RTL_OSVERSIONINFOEXW rtlinfo;
601         rtlinfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
602         ok(!pRtlGetVersion(&rtlinfo), "RtlGetVersion failed\n");
603 
604         if (rtlinfo.dwMajorVersion != 6 || rtlinfo.dwMinorVersion != 2)
605         {
606             win_skip("GetVersionEx and VerifyVersionInfo are faking values\n");
607             return;
608         }
609     }
610 
611     for (i = 0; i < sizeof(verify_version_tests)/sizeof(verify_version_tests[0]); i++)
612     {
613         struct verify_version_test *test = &verify_version_tests[i];
614         DWORD srcinfo = test->srcinfo;
615         ULONGLONG mask;
616 
617         if (servicepack == 0 && srcinfo & SRCVERSION_REQUIRES_SP)
618             continue;
619         srcinfo &= ~SRCVERSION_REQUIRES_SP;
620 
621         info.dwOSVersionInfoSize = sizeof(info);
622         GetVersionExA((OSVERSIONINFOA *)&info);
623 
624         switch (srcinfo)
625         {
626         case SRCVERSION_ZERO:
627             memset(&info, 0, sizeof(info));
628             break;
629         case SRCVERSION_INC_MINOR:
630             info.dwMinorVersion++;
631             break;
632         case SRCVERSION_INC_SP_MINOR:
633             info.wServicePackMinor++;
634             break;
635         case SRCVERSION_INC_SP_MAJOR:
636             info.wServicePackMajor++;
637             break;
638         case SRCVERSION_DEC_SP_MAJOR:
639             info.wServicePackMajor--;
640             break;
641         case SRCVERSION_DEC_MAJOR:
642             info.dwMajorVersion--;
643             break;
644         case SRCVERSION_INC_BUILD:
645             info.dwBuildNumber++;
646             break;
647         default:
648             ;
649         }
650 
651         mask = VerSetConditionMask(0, test->typemask1, test->condition1);
652         if (test->typemask2)
653             mask = VerSetConditionMask(mask, test->typemask2, test->condition2);
654         if (test->typemask3)
655             mask = VerSetConditionMask(mask, test->typemask3, test->condition3);
656         if (test->typemask4)
657             mask = VerSetConditionMask(mask, test->typemask4, test->condition4);
658 
659         SetLastError(0xdeadbeef);
660         ret = VerifyVersionInfoA(&info, test->verifymask, mask);
661     todo_wine_if(test->todo)
662     {
663         ok(test->err ? !ret : ret, "%u: unexpected return value %d.\n", i, ret);
664         if (!ret)
665             ok(GetLastError() == test->err, "%u: unexpected error code %d, expected %d.\n", i, GetLastError(), test->err);
666     }
667     }
668 
669     /* test handling of version numbers */
670     /* v3.10 is always less than v4.x even
671      * if the minor version is tested */
672     info.dwMajorVersion = 3;
673     info.dwMinorVersion = 10;
674     ret = VerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
675         VerSetConditionMask(VerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL),
676             VER_MAJORVERSION, VER_GREATER_EQUAL));
677     ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
678 
679     info.dwMinorVersion = 0;
680     info.wServicePackMajor = 10;
681     ret = VerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
682         VerSetConditionMask(VerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL),
683             VER_MAJORVERSION, VER_GREATER_EQUAL));
684     ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
685 
686     info.wServicePackMajor = 0;
687     info.wServicePackMinor = 10;
688     ret = VerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
689         VerSetConditionMask(VerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL),
690             VER_MAJORVERSION, VER_GREATER_EQUAL));
691     ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
692 
693     /* test bad dwOSVersionInfoSize */
694     info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
695     GetVersionExA((OSVERSIONINFOA *)&info);
696     info.dwOSVersionInfoSize = 0;
697     ret = VerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
698         VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL));
699     ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError());
700 }
701 
702 START_TEST(version)
703 {
704     init_function_pointers();
705 
706     test_GetProductInfo();
707     test_GetVersionEx();
708     test_VerifyVersionInfo();
709 }
710