BUG #689: Partial implementation of VerifyVersionInfo{A,W}

Vincent Béron vberon at mecano.gme.usherb.ca
Wed May 22 23:01:37 CDT 2002


It's only a partial implementation as I'm lacking a) the proper Windows
versions and b) a compiler I can trust to finish the testing needed on
Windows to fully implement VVI{A,W}. In particular, almost every call I
made to VVI ended up with a ERROR_BAD_ARGUMENTS, even when trying MSDN's
code or very basic things (like MajorVersion == 5). I was using a
pointer to the actual function (got by GetProcAddressA) since the .lib I
used (VC98 and mingw) lack it, and that may cause harm since the third
argument is a 64bit value instead of a 32bit value like most of the
rest. If somebody wants to check it, I have a little program I
developped that I can post.

Changelog:
 - Partial implementation of VerifyVersionInfo{A,W}.

Vincent
-------------- next part --------------
diff -urN wine-orig/dlls/kernel/kernel32.spec wine-pas-compil?/dlls/kernel/kernel32.spec
--- wine-orig/dlls/kernel/kernel32.spec	Tue May 14 17:13:54 2002
+++ wine-pas-compil?/dlls/kernel/kernel32.spec	Thu May 16 22:16:32 2002
@@ -963,7 +963,8 @@
 @ stdcall GetCalendarInfoW(long long long ptr long ptr) GetCalendarInfoW
 @ stdcall SetCalendarInfoA(long long long str) SetCalendarInfoA
 @ stdcall SetCalendarInfoW(long long long wstr) SetCalendarInfoW
-@ stdcall VerifyVersionInfoW(long long long long)VerifyVersionInfoW
+@ stdcall VerifyVersionInfoA(long long long long) VerifyVersionInfoA
+@ stdcall VerifyVersionInfoW(long long long long) VerifyVersionInfoW
 
 # XP extensions
 @ stdcall DebugActiveProcessStop(long) DebugActiveProcessStop
diff -urN wine-orig/include/winbase.h wine-pas-compil?/include/winbase.h
--- wine-orig/include/winbase.h	Tue May 21 19:11:08 2002
+++ wine-pas-compil?/include/winbase.h	Sat May 18 14:46:16 2002
@@ -874,6 +874,10 @@
 
 #define VER_SET_CONDITION(_m_,_t_,_c_) ((_m_)=VerSetConditionMask((_m_),(_t_),(_c_)))
 
+BOOL WINAPI VerifyVersionInfoA(LPOSVERSIONINFOEXA,DWORD,DWORDLONG);
+BOOL WINAPI VerifyVersionInfoW(LPOSVERSIONINFOEXW,DWORD,DWORDLONG);
+#define VerifyVersionInfo WINELIB_NAME_AW(VerifyVersionInfo)
+
 #define	VER_PLATFORM_WIN32s             	0
 #define	VER_PLATFORM_WIN32_WINDOWS      	1
 #define	VER_PLATFORM_WIN32_NT           	2
diff -urN wine-orig/misc/version.c wine-pas-compil?/misc/version.c
--- wine-orig/misc/version.c	Fri May 10 08:40:01 2002
+++ wine-pas-compil?/misc/version.c	Wed May 22 23:47:21 2002
@@ -55,7 +55,7 @@
 {
     LONG             getVersion16; 
     LONG             getVersion32;
-    OSVERSIONINFOA getVersionEx;
+    OSVERSIONINFOEXA getVersionEx;
 } VERSION_DATA;
 
 /* FIXME: compare values below with original and fix */
@@ -67,7 +67,8 @@
 	MAKELONG( 0x0003, 0x8000 ),
 	{
             sizeof(OSVERSIONINFOA), 2, 0, 0,
-            VER_PLATFORM_WIN32s, "Win32s 1.3" 
+            VER_PLATFORM_WIN32s, "Win32s 1.3",
+	    0, 0, 0, 0, 0
 	}
     },
     /* WIN30 FIXME: verify values */
@@ -76,7 +77,8 @@
 	MAKELONG( 0x0003, 0x8000 ),
 	{
             sizeof(OSVERSIONINFOA), 3, 0, 0,
-            VER_PLATFORM_WIN32s, "Win32s 1.3" 
+            VER_PLATFORM_WIN32s, "Win32s 1.3",
+	    0, 0, 0, 0, 0
 	}
     },
     /* WIN31 */
@@ -85,7 +87,8 @@
 	MAKELONG( 0x0a03, 0x8000 ),
 	{
             sizeof(OSVERSIONINFOA), 3, 10, 0,
-            VER_PLATFORM_WIN32s, "Win32s 1.3" 
+            VER_PLATFORM_WIN32s, "Win32s 1.3",
+	    0, 0, 0, 0, 0
 	}
     },
     /* WIN95 */
@@ -103,7 +106,8 @@
              * http://support.microsoft.com/support/kb/articles/q158/2/38.asp
              */
             sizeof(OSVERSIONINFOA), 4, 0, 0x40003B6,
-            VER_PLATFORM_WIN32_WINDOWS, ""
+            VER_PLATFORM_WIN32_WINDOWS, "",
+	    0, 0, 0, 0, 0
         }
     },
     /* WIN98 */
@@ -115,7 +119,8 @@
              * Win98SE: 4, 10, 0x40A08AE, " A "
              */
             sizeof(OSVERSIONINFOA), 4, 10, 0x40A07CE,
-            VER_PLATFORM_WIN32_WINDOWS, " "
+            VER_PLATFORM_WIN32_WINDOWS, " ",
+	    0, 0, 0, 0, 0
         }
     },
     /* WINME */
@@ -124,7 +129,8 @@
         0xC0005A04,
         {
             sizeof(OSVERSIONINFOA), 4, 90, 0x45A0BB8,
-            VER_PLATFORM_WIN32_WINDOWS, " "
+            VER_PLATFORM_WIN32_WINDOWS, " ",
+	    0, 0, 0, 0, 0
         }
     },
     /* NT351 */
@@ -133,7 +139,8 @@
         0x04213303,
         {
             sizeof(OSVERSIONINFOA), 3, 51, 0x421,
-            VER_PLATFORM_WIN32_NT, "Service Pack 2"
+            VER_PLATFORM_WIN32_NT, "Service Pack 2",
+	    0, 0, 0, 0, 0
         }
     },
     /* NT40 */
@@ -142,7 +149,8 @@
         0x05650004,
         {
             sizeof(OSVERSIONINFOA), 4, 0, 0x565,
-            VER_PLATFORM_WIN32_NT, "Service Pack 6"
+            VER_PLATFORM_WIN32_NT, "Service Pack 6",
+	    6, 0, 0, VER_NT_WORKSTATION, 0
         }
     },
     /* NT2K */
@@ -151,7 +159,8 @@
         0x08930005,
         {
             sizeof(OSVERSIONINFOA), 5, 0, 0x893,
-            VER_PLATFORM_WIN32_NT, "Service Pack 2"
+            VER_PLATFORM_WIN32_NT, "Service Pack 2",
+	    2, 0, 0, VER_NT_WORKSTATION, 30 /* FIXME: Great, a reserved field with a value! */
         }
     },
     /* WINXP */
@@ -160,7 +169,8 @@
         0x0A280105,
         {
             sizeof(OSVERSIONINFOA), 5, 1, 0xA28,
-            VER_PLATFORM_WIN32_NT, ""
+            VER_PLATFORM_WIN32_NT, "",
+	    0, 0, 0, VER_NT_WORKSTATION, 0 /* FIXME: Verify last 5 values */
         }
     }
 };
@@ -472,10 +482,14 @@
 BOOL WINAPI GetVersionExA(OSVERSIONINFOA *v)
 {
     WINDOWS_VERSION ver = VERSION_GetVersion();
-    if (v->dwOSVersionInfoSize < sizeof(OSVERSIONINFOA))
+    LPOSVERSIONINFOEXA vex;
+
+    if (v->dwOSVersionInfoSize != sizeof(OSVERSIONINFOA) &&
+	v->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXA))
     {
-        WARN("wrong OSVERSIONINFO size from app (got: %ld, expected: %d)\n",
-                        v->dwOSVersionInfoSize, sizeof(OSVERSIONINFOA));
+        WARN("wrong OSVERSIONINFO size from app (got: %ld, expected: %d or %d)\n",
+                        v->dwOSVersionInfoSize, sizeof(OSVERSIONINFOA),
+			sizeof(OSVERSIONINFOEXA));
         SetLastError(ERROR_INSUFFICIENT_BUFFER);
         return FALSE;
     }
@@ -484,6 +498,13 @@
     v->dwBuildNumber  = VersionData[ver].getVersionEx.dwBuildNumber;
     v->dwPlatformId   = VersionData[ver].getVersionEx.dwPlatformId;
     strcpy( v->szCSDVersion, VersionData[ver].getVersionEx.szCSDVersion );
+    if(v->dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXA)) {
+	vex = (LPOSVERSIONINFOEXA) v;
+	vex->wServicePackMajor = VersionData[ver].getVersionEx.wServicePackMajor;
+	vex->wServicePackMinor = VersionData[ver].getVersionEx.wServicePackMinor;
+	vex->wSuiteMask = VersionData[ver].getVersionEx.wSuiteMask;
+	vex->wProductType = VersionData[ver].getVersionEx.wProductType;
+    }
     return TRUE;
 }
 
@@ -494,11 +515,14 @@
 BOOL WINAPI GetVersionExW(OSVERSIONINFOW *v)
 {
     WINDOWS_VERSION ver = VERSION_GetVersion();
+    LPOSVERSIONINFOEXW vex;
 
-    if (v->dwOSVersionInfoSize < sizeof(OSVERSIONINFOW))
+    if (v->dwOSVersionInfoSize != sizeof(OSVERSIONINFOW) &&
+	v->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXW))
     {
-        WARN("wrong OSVERSIONINFO size from app (got: %ld, expected: %d)\n",
-			v->dwOSVersionInfoSize, sizeof(OSVERSIONINFOW));
+        WARN("wrong OSVERSIONINFO size from app (got: %ld, expected: %d or %d)\n",
+			v->dwOSVersionInfoSize, sizeof(OSVERSIONINFOW),
+			sizeof(OSVERSIONINFOEXW));
         SetLastError(ERROR_INSUFFICIENT_BUFFER);
         return FALSE;
     }
@@ -508,19 +532,276 @@
     v->dwPlatformId   = VersionData[ver].getVersionEx.dwPlatformId;
     MultiByteToWideChar( CP_ACP, 0, VersionData[ver].getVersionEx.szCSDVersion, -1,
                          v->szCSDVersion, sizeof(v->szCSDVersion)/sizeof(WCHAR) );
+    if(v->dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXW)) {
+	vex = (LPOSVERSIONINFOEXW) v;
+	vex->wServicePackMajor = VersionData[ver].getVersionEx.wServicePackMajor;
+	vex->wServicePackMinor = VersionData[ver].getVersionEx.wServicePackMinor;
+	vex->wSuiteMask = VersionData[ver].getVersionEx.wSuiteMask;
+	vex->wProductType = VersionData[ver].getVersionEx.wProductType;
+    }
     return TRUE;
 }
 
 
+/******************************************************************************
+ *        VerifyVersionInfoA   (KERNEL32.@)
+ */
+BOOL WINAPI VerifyVersionInfoA( LPOSVERSIONINFOEXA lpVersionInfo, DWORD dwTypeMask,
+                                DWORDLONG dwlConditionMask)
+{
+    OSVERSIONINFOEXW verW;
+
+    verW.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
+    verW.dwMajorVersion = lpVersionInfo->dwMajorVersion;
+    verW.dwMinorVersion = lpVersionInfo->dwMinorVersion;
+    verW.dwBuildNumber = lpVersionInfo->dwBuildNumber;
+    verW.dwPlatformId = lpVersionInfo->dwPlatformId;
+    verW.wServicePackMajor = lpVersionInfo->wServicePackMajor;
+    verW.wServicePackMinor = lpVersionInfo->wServicePackMinor;
+    verW.wSuiteMask = lpVersionInfo->wSuiteMask;
+    verW.wProductType = lpVersionInfo->wProductType;
+    verW.wReserved = lpVersionInfo->wReserved;
+
+    return VerifyVersionInfoW(&verW, dwTypeMask, dwlConditionMask);
+}
+
 
 /******************************************************************************
  *        VerifyVersionInfoW   (KERNEL32.@)
  */
-BOOL WINAPI VerifyVersionInfoW( /* LPOSVERSIONINFOEXW */ LPVOID lpVersionInfo, DWORD dwTypeMask,
+BOOL WINAPI VerifyVersionInfoW( LPOSVERSIONINFOEXW lpVersionInfo, DWORD dwTypeMask,
                                 DWORDLONG dwlConditionMask)
 {
-    FIXME("%p %lu %llx\n", lpVersionInfo, dwTypeMask, dwlConditionMask);
-    return TRUE;
+    OSVERSIONINFOEXW ver;
+    BOOL res, error_set;
+
+    FIXME("(%p,%lu,%llx): Not all cases correctly implemented yet\n", lpVersionInfo, dwTypeMask, dwlConditionMask);
+    /* FIXME:
+	- Check the following special case on Windows (various versions):
+	  o lp->wSuiteMask == 0 and ver.wSuiteMask != 0 and VER_AND/VER_OR
+	  o lp->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXW)
+	- MSDN talks about some tests being impossible. Check what really happens.
+     */
+
+    ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
+    if(!GetVersionExW((LPOSVERSIONINFOW) &ver))
+	return FALSE;
+
+    res = TRUE;
+    error_set = FALSE;
+    if(!(dwTypeMask && dwlConditionMask)) {
+	res = FALSE;
+	SetLastError(ERROR_BAD_ARGUMENTS);
+	error_set = TRUE;
+    }
+    if(dwTypeMask & VER_PRODUCT_TYPE)
+	switch(dwlConditionMask >> 7*3 & 0x07) {
+	    case VER_EQUAL:
+		if(ver.wProductType != lpVersionInfo->wProductType)
+		    res = FALSE;
+		break;
+	    case VER_GREATER:
+		if(ver.wProductType <= lpVersionInfo->wProductType)
+		    res = FALSE;
+		break;
+	    case VER_GREATER_EQUAL:
+		if(ver.wProductType < lpVersionInfo->wProductType)
+		    res = FALSE;
+		break;
+	    case VER_LESS:
+		if(ver.wProductType >= lpVersionInfo->wProductType)
+		    res = FALSE;
+		break;
+	    case VER_LESS_EQUAL:
+		if(ver.wProductType > lpVersionInfo->wProductType)
+		    res = FALSE;
+		break;
+	    default:
+	        res = FALSE;
+		SetLastError(ERROR_BAD_ARGUMENTS);
+		error_set = TRUE;
+	}
+    if(dwTypeMask & VER_SUITENAME && res)
+	switch(dwlConditionMask >> 6*3 & 0x07) {
+	    case VER_AND:
+		if((lpVersionInfo->wSuiteMask & ver.wSuiteMask) != lpVersionInfo->wSuiteMask)
+		    res = FALSE;
+		break;
+	    case VER_OR:
+		if(!(lpVersionInfo->wSuiteMask & ver.wSuiteMask) && lpVersionInfo->wSuiteMask)
+		    res = FALSE;
+		break;
+	    default:
+	        res = FALSE;
+		SetLastError(ERROR_BAD_ARGUMENTS);
+		error_set = TRUE;
+	}
+    if(dwTypeMask & VER_PLATFORMID && res)
+	switch(dwlConditionMask >> 3*3 & 0x07) {
+	    case VER_EQUAL:
+		if(ver.dwPlatformId != lpVersionInfo->dwPlatformId)
+		    res = FALSE;
+		break;
+	    case VER_GREATER:
+		if(ver.dwPlatformId <= lpVersionInfo->dwPlatformId)
+		    res = FALSE;
+		break;
+	    case VER_GREATER_EQUAL:
+		if(ver.dwPlatformId < lpVersionInfo->dwPlatformId)
+		    res = FALSE;
+		break;
+	    case VER_LESS:
+		if(ver.dwPlatformId >= lpVersionInfo->dwPlatformId)
+		    res = FALSE;
+		break;
+	    case VER_LESS_EQUAL:
+		if(ver.dwPlatformId > lpVersionInfo->dwPlatformId)
+		    res = FALSE;
+		break;
+	    default:
+	        res = FALSE;
+		SetLastError(ERROR_BAD_ARGUMENTS);
+		error_set = TRUE;
+	}
+    if(dwTypeMask & VER_BUILDNUMBER && res)
+	switch(dwlConditionMask >> 2*3 & 0x07) {
+	    case VER_EQUAL:
+		if(ver.dwBuildNumber != lpVersionInfo->dwBuildNumber)
+		    res = FALSE;
+		break;
+	    case VER_GREATER:
+		if(ver.dwBuildNumber <= lpVersionInfo->dwBuildNumber)
+		    res = FALSE;
+		break;
+	    case VER_GREATER_EQUAL:
+		if(ver.dwBuildNumber < lpVersionInfo->dwBuildNumber)
+		    res = FALSE;
+		break;
+	    case VER_LESS:
+		if(ver.dwBuildNumber >= lpVersionInfo->dwBuildNumber)
+		    res = FALSE;
+		break;
+	    case VER_LESS_EQUAL:
+		if(ver.dwBuildNumber > lpVersionInfo->dwBuildNumber)
+		    res = FALSE;
+		break;
+	    default:
+	        res = FALSE;
+		SetLastError(ERROR_BAD_ARGUMENTS);
+		error_set = TRUE;
+	}
+    if(dwTypeMask & VER_MAJORVERSION && res)
+	switch(dwlConditionMask >> 1*3 & 0x07) {
+	    case VER_EQUAL:
+		if(ver.dwMajorVersion != lpVersionInfo->dwMajorVersion)
+		    res = FALSE;
+		break;
+	    case VER_GREATER:
+		if(ver.dwMajorVersion <= lpVersionInfo->dwMajorVersion)
+		    res = FALSE;
+		break;
+	    case VER_GREATER_EQUAL:
+		if(ver.dwMajorVersion < lpVersionInfo->dwMajorVersion)
+		    res = FALSE;
+		break;
+	    case VER_LESS:
+		if(ver.dwMajorVersion >= lpVersionInfo->dwMajorVersion)
+		    res = FALSE;
+		break;
+	    case VER_LESS_EQUAL:
+		if(ver.dwMajorVersion > lpVersionInfo->dwMajorVersion)
+		    res = FALSE;
+		break;
+	    default:
+	        res = FALSE;
+		SetLastError(ERROR_BAD_ARGUMENTS);
+		error_set = TRUE;
+	}
+    if(dwTypeMask & VER_MINORVERSION && res)
+	switch(dwlConditionMask >> 0*3 & 0x07) {
+	    case VER_EQUAL:
+		if(ver.dwMinorVersion != lpVersionInfo->dwMinorVersion)
+		    res = FALSE;
+		break;
+	    case VER_GREATER:
+		if(ver.dwMinorVersion <= lpVersionInfo->dwMinorVersion)
+		    res = FALSE;
+		break;
+	    case VER_GREATER_EQUAL:
+		if(ver.dwMinorVersion < lpVersionInfo->dwMinorVersion)
+		    res = FALSE;
+		break;
+	    case VER_LESS:
+		if(ver.dwMinorVersion >= lpVersionInfo->dwMinorVersion)
+		    res = FALSE;
+		break;
+	    case VER_LESS_EQUAL:
+		if(ver.dwMinorVersion > lpVersionInfo->dwMinorVersion)
+		    res = FALSE;
+		break;
+	    default:
+	        res = FALSE;
+		SetLastError(ERROR_BAD_ARGUMENTS);
+		error_set = TRUE;
+	}
+    if(dwTypeMask & VER_SERVICEPACKMAJOR && res)
+	switch(dwlConditionMask >> 5*3 & 0x07) {
+	    case VER_EQUAL:
+		if(ver.wServicePackMajor != lpVersionInfo->wServicePackMajor)
+		    res = FALSE;
+		break;
+	    case VER_GREATER:
+		if(ver.wServicePackMajor <= lpVersionInfo->wServicePackMajor)
+		    res = FALSE;
+		break;
+	    case VER_GREATER_EQUAL:
+		if(ver.wServicePackMajor < lpVersionInfo->wServicePackMajor)
+		    res = FALSE;
+		break;
+	    case VER_LESS:
+		if(ver.wServicePackMajor >= lpVersionInfo->wServicePackMajor)
+		    res = FALSE;
+		break;
+	    case VER_LESS_EQUAL:
+		if(ver.wServicePackMajor > lpVersionInfo->wServicePackMajor)
+		    res = FALSE;
+		break;
+	    default:
+	        res = FALSE;
+		SetLastError(ERROR_BAD_ARGUMENTS);
+		error_set = TRUE;
+	}
+    if(dwTypeMask & VER_SERVICEPACKMINOR && res)
+	switch(dwlConditionMask >> 4*3 & 0x07) {
+	    case VER_EQUAL:
+		if(ver.wServicePackMinor != lpVersionInfo->wServicePackMinor)
+		    res = FALSE;
+		break;
+	    case VER_GREATER:
+		if(ver.wServicePackMinor <= lpVersionInfo->wServicePackMinor)
+		    res = FALSE;
+		break;
+	    case VER_GREATER_EQUAL:
+		if(ver.wServicePackMinor < lpVersionInfo->wServicePackMinor)
+		    res = FALSE;
+		break;
+	    case VER_LESS:
+		if(ver.wServicePackMinor >= lpVersionInfo->wServicePackMinor)
+		    res = FALSE;
+		break;
+	    case VER_LESS_EQUAL:
+		if(ver.wServicePackMinor > lpVersionInfo->wServicePackMinor)
+		    res = FALSE;
+		break;
+	    default:
+	        res = FALSE;
+		SetLastError(ERROR_BAD_ARGUMENTS);
+		error_set = TRUE;
+	}
+
+    if(!(res || error_set))
+	SetLastError(ERROR_OLD_WIN_VERSION);
+    return res;
 }
 
 


More information about the wine-patches mailing list