Add a WINEVER environment variable

Mike Hearn mh at codeweavers.com
Wed Jul 21 13:50:37 CDT 2004


In these times of programs that expect varying versions of Windows, it's
useful to be able to change the version reported easily on a per-app basis
from the command line. Otherwise you have to keep editing the config file
and (maybe) restarting the wineserver.

One question: is it good style to calculate the maximum buffer size that
makes sense like I do here, or is it acceptable to just choose an
arbitrarily high number and use the stack in cases where an overflow isn't
possible?

Some of this is imported from CrossOver.

ChangeLog:
Add a WINEVER environment variable, refactor the version parsing code.

Index: documentation/wine.man.in
===================================================================
RCS file: /home/wine/wine/documentation/wine.man.in,v
retrieving revision 1.53
diff -u -p -r1.53 wine.man.in
--- documentation/wine.man.in   6 May 2004 23:51:43 -0000       1.53
+++ documentation/wine.man.in   21 Jul 2004 18:43:12 -0000
@@ -105,6 +105,11 @@ try to load
 and if this doesn't exist it will then look for a file named "wine" in
 the path and in a few other likely locations.
 .TP
+.I WINEVER
+Specifies the Windows version that will be reported to the
+application. Takes the same form as the equivalent key in the
+config file/registry.
+.TP
 .I WINEDEBUG
 Turns debugging messages on or off. The syntax of the variable is
 of the form
Index: dlls/ntdll/version.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/version.c,v
retrieving revision 1.5
diff -u -p -r1.5 version.c
--- dlls/ntdll/version.c        14 Jul 2004 21:44:10 -0000      1.5
+++ dlls/ntdll/version.c        21 Jul 2004 18:43:14 -0000
@@ -175,7 +175,7 @@ static const char * const debug_names[NB
 };
  
 /* if one of the following dlls is importing ntdll the windows
-version autodetection switches wine to unicode (nt 3.51 or 4.0) */
+   version autodetection switches wine to unicode (nt 3.51 or 4.0) */
 static const WCHAR special_dlls[][16] =
 {
     {'c','o','m','d','l','g','3','2','.','d','l','l',0},
@@ -189,26 +189,33 @@ static const WCHAR special_dlls[][16] =
 static BOOL versionForced = FALSE;
 static WINDOWS_VERSION forcedWinVersion; /* init value irrelevant */
  
+static void explain_versions(BOOL registry)
+{
+    int i, len;
+
+    MESSAGE("Invalid Windows version value specified %s\n", registry ? "in config file." : "in WINEVER" );
+    MESSAGE("Valid versions are:" );
+    for (i = 0; i < NB_WINDOWS_VERSIONS; i++)
+    {
+        /* only list the first, "official" alias in case of aliases */
+        const char *pCurr = WinVersionNames[i];
+        const char *p = strchr(pCurr, ',');
+        len = (p) ? p - pCurr : strlen(pCurr);
+
+        MESSAGE(" '%.*s'%c", (int)len, pCurr, (i == NB_WINDOWS_VERSIONS - 1) ? '\n' : ',' );
+    }
+}
+
 /**********************************************************************
- *         parse_win_version
- *
- * Parse the contents of the Version key.
+ *         parse_version_string
  */
-static BOOL parse_win_version( HKEY hkey )
+static BOOL parse_version_string( const WCHAR *str, DWORD length, BOOL registry )
 {
-    static const WCHAR WindowsW[] = {'W','i','n','d','o','w','s',0};
-
-    UNICODE_STRING valueW;
-    char tmp[64], buffer[50];
-    KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)tmp;
-    DWORD count, len;
     int i;
+    DWORD len;
+    char buffer[50];
  
-    RtlInitUnicodeString( &valueW, WindowsW );
-    if (NtQueryValueKey( hkey, &valueW, KeyValuePartialInformation, tmp, sizeof(tmp), &count ))
-        return FALSE;
-
-    RtlUnicodeToMultiByteN( buffer, sizeof(buffer)-1, &len, (WCHAR *)info->Data, info->DataLength );
+    RtlUnicodeToMultiByteN( buffer, sizeof(buffer)-1, &len, str, length );
     buffer[len] = 0;
  
     for (i = 0; i < NB_WINDOWS_VERSIONS; i++)
@@ -229,20 +236,32 @@ static BOOL parse_win_version( HKEY hkey
         } while (p);
     }
  
-    MESSAGE("Invalid Windows version value '%s' specified in config file.\n", buffer );
-    MESSAGE("Valid versions are:" );
-    for (i = 0; i < NB_WINDOWS_VERSIONS; i++)
-    {
-        /* only list the first, "official" alias in case of aliases */
-        const char *pCurr = WinVersionNames[i];
-        const char *p = strchr(pCurr, ',');
-        len = (p) ? p - pCurr : strlen(pCurr);
-
-        MESSAGE(" '%.*s'%c", (int)len, pCurr, (i == NB_WINDOWS_VERSIONS - 1) ? '\n' : ',' );
-    }
+    explain_versions( registry );
+
     return FALSE;
 }
  
+/**********************************************************************
+ *         parse_win_version
+ *
+ * Parse the contents of the Version key.
+ */
+static BOOL parse_win_version( HKEY hkey )
+{
+    static const WCHAR WindowsW[] = {'W','i','n','d','o','w','s',0};
+
+    UNICODE_STRING valueW;
+    char tmp[64];
+    KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)tmp;
+    DWORD count;
+
+    RtlInitUnicodeString( &valueW, WindowsW );
+    if (NtQueryValueKey( hkey, &valueW, KeyValuePartialInformation, tmp, sizeof(tmp), &count ))
+        return FALSE;
+
+    return parse_version_string( (WCHAR *)info->Data, info->DataLength, TRUE );
+}
+
  
 /**********************************************************************
  *         VERSION_Init
@@ -250,8 +269,9 @@ static BOOL parse_win_version( HKEY hkey
 void VERSION_Init( const WCHAR *appname )
 {
     OBJECT_ATTRIBUTES attr;
-    UNICODE_STRING nameW;
+    UNICODE_STRING nameW, envW;
     HKEY hkey, config_key;
+    NTSTATUS status;
     static const WCHAR configW[] = {'M','a','c','h','i','n','e','\\',
                                     'S','o','f','t','w','a','r','e','\\',
                                     'W','i','n','e','\\',
@@ -259,7 +279,29 @@ void VERSION_Init( const WCHAR *appname
                                     'C','o','n','f','i','g',0};
     static const WCHAR appdefaultsW[] = {'A','p','p','D','e','f','a','u','l','t','s','\\',0};
     static const WCHAR versionW[] = {'\\','V','e','r','s','i','o','n',0};
+    static const WCHAR envnameW[] = {'W','I','N','E','V','E','R',0};
+    int i;
+
+    /* find the length of the longest version string */
+    for (i = 0; i < NB_WINDOWS_VERSIONS; i++)
+    {
+        int l = strlen( WinVersionNames[i] );
+        if (l > envW.MaximumLength) envW.MaximumLength = l;
+    }
  
+    envW.Buffer = RtlAllocateHeap( GetProcessHeap(), 0, envW.MaximumLength );
+    RtlInitUnicodeString( &nameW, envnameW );
+    status = RtlQueryEnvironmentVariable_U( NULL, &nameW, &envW );
+    if (status == STATUS_SUCCESS)
+    {
+        TRACE("getting version from WINEVER\n");
+        parse_version_string( envW.Buffer, envW.Length, FALSE );
+        RtlFreeHeap( GetProcessHeap(), 0, envW.Buffer );
+        return;
+    }
+    else if (status == STATUS_BUFFER_TOO_SMALL) explain_versions( FALSE );
+    RtlFreeHeap( GetProcessHeap(), 0, envW.Buffer );
+
     attr.Length = sizeof(attr);
     attr.RootDirectory = 0;
     attr.ObjectName = &nameW;





More information about the wine-patches mailing list