[tools] testbot/SetWinLocale: Re-set --locale if it does not stick after the reboot.

Francois Gouget fgouget at codeweavers.com
Mon Jan 31 09:06:32 CST 2022


On Windows 10 21H1 some process typically resets the --locale and
--country some time after the login (except when they are changed
through the GUI)!!!
So wait for the reset to happen and set them again so they are as
expected at least until the next reboot :-(

Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
---
This is why UserDefaultLCID is wrong in many of the TestBot VMs :-( 

Unfortunately I did not find what's causing the settings to be reset, 
and what's the difference with changing them through the GUI. At least 
with this patch GetUserDefaultLCID() and GetUserGeoID() return the 
expected values in the tests (except when LibvirtTool triggers another 
reboot before taking the snapshot).
---
 testbot/bin/SetWinLocale | 92 ++++++++++++++++++++++++++++++++--------
 1 file changed, 74 insertions(+), 18 deletions(-)

diff --git a/testbot/bin/SetWinLocale b/testbot/bin/SetWinLocale
index 18cbfc22c5..81bb2212b1 100755
--- a/testbot/bin/SetWinLocale
+++ b/testbot/bin/SetWinLocale
@@ -41,6 +41,8 @@ use WineTestBot::Log;
 use WineTestBot::TestAgent;
 use WineTestBot::Utils;
 
+my $HKCU_INTERNATIONAL = "HKCU\\Control Panel\\International";
+my $HKCU_GEO = "HKCU\\Control Panel\\International\\Geo";
 my $HKCU_USER_PROFILE = "HKCU\\Control Panel\\International\\User Profile";
 
 
@@ -499,12 +501,18 @@ if (defined $Usage)
   print "                 ISO 639-1 language code and CC an ISO 3166-1 alpha-2 country\n";
   print "                 code.\n";
   print "  --locale LOC   Specifies the user formats (see --defaults).\n";
+  print "                 . Windows 10 may reset this setting a few seconds after a\n";
+  print "                   the next log in. Thus one should not expect this change to\n";
+  print "                   persist after a reboot.\n";
   print "                 . Windows 10 GUI: Time & language -> Region -> Regional\n";
   print "                   format.\n";
   print "                 . APIs: GetUserDefaultLCID().\n";
   print "                 . Powershell: Set-Culture LOC\n";
   print "  --country CTY  Specifies the location using only the country part of the\n";
   print "                 Windows locale (see --defaults).\n";
+  print "                 . Windows 10 may reset this setting a few seconds after a\n";
+  print "                   the next log in. Thus one should not expect this change to\n";
+  print "                   persist after a reboot.\n";
   print "                 . Windows 10 GUI: Time & language -> Region -> Country.\n";
   print "                 . APIs: GetUserGeoID().\n";
   print "                 . Powershell: Set-WinHomeLocation -GeoId CTY-ID\n";
@@ -555,9 +563,10 @@ if (defined $Usage)
   print "                 . Powershell (Windows 11+): Copy-UserInternationalSettingsToSystem -NewUser \$True\n";
   print "                 . Intl.cpl: CopySettingsToDefaultUserAcct='true'\n";
   print "  --no-def-copy  Do not copy the current locales to the default user account.\n";
-  print "  --no-reboot    Do not reboot Windows. Some locale changes only take effect\n";
-  print "                 after a reboot so this option should only be used for\n";
-  print "                 debugging.\n";
+  print "  --no-reboot    Do not reboot Windows. Some locale changes will only take\n";
+  print "                 effect after the next reboot. This will also prevent working\n";
+  print "                 around cases where some locale changes do not stick after a\n";
+  print "                 reboot. So this should only be used for debugging.\n";
   print "  --debug        Show more detailed information about progress.\n";
   print "  --help         Shows this usage message.\n";
   exit 0;
@@ -713,9 +722,10 @@ sub ShowWinSettings($)
   print "InputMethod     (--keyboard) = ", Value2Str($Settings->{DefInputMethod}), "\n";
 }
 
+my $InitialSettings = GetWinSettings();
 if ($OptShow)
 {
-  ShowWinSettings(GetWinSettings());
+  ShowWinSettings($InitialSettings);
   Cleanup();
   exit(0);
 }
@@ -814,24 +824,32 @@ $OptKeyboard ||= $OptDefault;
 
 
 #
-# Change the Windows locale
+# Helper to change the Windows locales
 #
 
-my $Cmd = ["powershell.exe", "-ExecutionPolicy", "ByPass", "-File",
-           "$name0.ps1", "locales", $OptLocale || ".", $CountryId || ".",
-           $OptSystem || ".", $OptUTF8 ? "true" : "false", $OptMUI || ".",
-           $KeyboardIds ? $KeyboardIds->[0] : ".",
-           $OptSysCopy ? "true" : "false", $OptDefCopy ? "true" : "false"];
-Debug(Elapsed($Start), " Running: ", join(" ", @$Cmd), "\n");
-my $Ret = $TA->RunAndWait($Cmd, 0, 30, undef, "$name0.out", "$name0.out");
-FatalError("$name0.ps1 locales failed: ", $TA->GetLastError(), "\n") if ($Ret < 0);
-my $Out = $TA->GetFileToString("$name0.out");
-foreach my $Line (split /\n/, $Out || "")
+sub SetWinLocales($$$$$$$$)
 {
-  $Line =~ s/\r$//;
-  Info("$Line\n");
+  my ($SysCopy, $DefCopy, $Locale, $CountryId, $System, $UTF8, $MUI, $KeyboardIds) = @_;
+
+  my $Cmd = ["powershell.exe", "-ExecutionPolicy", "ByPass", "-File",
+             "$name0.ps1", "locales", $Locale || ".", $CountryId || ".",
+             $System || ".", $UTF8 ? "true" : "false", $MUI || ".",
+             $KeyboardIds ? $KeyboardIds->[0] : ".",
+             $SysCopy ? "true" : "false", $DefCopy ? "true" : "false"];
+  Debug(Elapsed($Start), " Running: ", join(" ", @$Cmd), "\n");
+  my $Ret = $TA->RunAndWait($Cmd, 0, 30, undef, "$name0.out", "$name0.out");
+  FatalError("$name0.ps1 locales failed: ", $TA->GetLastError(), "\n") if ($Ret < 0);
+  my $Out = $TA->GetFileToString("$name0.out");
+  foreach my $Line (split /\n/, $Out || "")
+  {
+    $Line =~ s/\r$//;
+    Info("$Line\n");
+  }
 }
 
+SetWinLocales($OptSysCopy, $OptDefCopy, $OptLocale, $CountryId,
+              $OptSystem, $OptUTF8, $OptMUI, $KeyboardIds);
+
 
 #
 # Reboot to finalize the changes
@@ -839,7 +857,7 @@ foreach my $Line (split /\n/, $Out || "")
 
 if ($OptReboot)
 {
-  $Cmd = ["shutdown.exe", "/r", "/t", "0"];
+  my $Cmd = ["shutdown.exe", "/r", "/t", "0"];
   Debug(Elapsed($Start), " Rebooting: ", join(" ", @$Cmd), "\n");
   $TA->Run($Cmd, 0);
   # Note that we cannot wait for this command since it reboots Windows
@@ -853,6 +871,44 @@ if ($OptReboot)
   {
     FatalError("could not reconnect to $OptHostName after the reboot: ", $TA->GetLastError(), "\n");
   }
+
+  # Skip this check on pre-Windows 10 versions, i.e. those that don't have
+  # 'CountryName' and if the settings were not changed in the first place.
+  if ($InitialSettings->{CountryName} and
+      (($OptLocale and $InitialSettings->{Locale} ne $OptLocale) or
+       ($OptCountry and $InitialSettings->{Country} ne $CountryId)))
+  {
+    # On Windows 10 21H1 some process typically resets the --locale and
+    # --country some time after the login!!!
+    # This also happens when making the change through the Powershell's
+    # Set-Culture and Set-WinHomeLocation calls, but not when manually going
+    # through the GUI.
+    # So wait for the reset to happen and re-set them :-(
+    my $Expected = $OptLocale ? "--locale $OptLocale" : "";
+    $Expected .= !$OptCountry ? "" : (($Expected ? " and " : "") . ("--country $OptCountry"));
+    Debug(Elapsed($Start), " Expecting $Expected to get reverted\n");
+    foreach (1..30)
+    {
+      my $Reverted;
+      if ($OptCountry)
+      {
+        my $Nation = RegGetValue($HKCU_GEO, "Nation");
+        $Reverted = "--country $Nation" if ($Nation ne $CountryId);
+      }
+      else
+      {
+        my $LocaleName = RegGetValue($HKCU_INTERNATIONAL, "LocaleName");
+        $Reverted = "--locale $LocaleName" if ($LocaleName ne $OptLocale);
+      }
+      if ($Reverted)
+      {
+        Warning("$Expected got reverted to $Reverted. Setting them again but this will not stick across reboots\n");
+        SetWinLocales(undef, undef, $OptLocale, $CountryId, undef, undef, undef, undef);
+        last;
+      }
+      sleep(2);
+    }
+  }
 }
 
 
-- 
2.30.2



More information about the wine-devel mailing list