Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

win_region - fix format issues when using psrp #55487

Merged
merged 1 commit into from
Apr 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelogs/fragments/win_region-format.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bugfixes:
- win_region - Fix the check for ``format`` when running on the ``psrp`` connection plugin
109 changes: 82 additions & 27 deletions lib/ansible/modules/windows/win_region.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,38 @@ using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace Ansible {
namespace Ansible.WinRegion {

public class NativeMethods
{
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int GetLocaleInfoEx(
String lpLocaleName,
UInt32 LCType,
StringBuilder lpLCData,
int cchData);

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int GetSystemDefaultLocaleName(
IntPtr lpLocaleName,
int cchLocaleName);

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int GetUserDefaultLocaleName(
IntPtr lpLocaleName,
int cchLocaleName);
}

public class LocaleHelper {
private String Locale;

public LocaleHelper(String locale) {
Locale = locale;
}

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int GetLocaleInfoEx(String lpLocaleName, UInt32 LCType, StringBuilder lpLCData, int cchData);

public String GetValueFromType(UInt32 LCType) {
StringBuilder data = new StringBuilder(500);
int result = GetLocaleInfoEx(Locale, LCType, data, 500);
int result = NativeMethods.GetLocaleInfoEx(Locale, LCType, data, 500);
if (result == 0)
throw new Exception(String.Format("Error getting locale info with legacy method: {0}", new Win32Exception(Marshal.GetLastWin32Error()).Message));

Expand All @@ -47,6 +65,59 @@ namespace Ansible {
}
}
"@
$original_tmp = $env:TMP
$env:TMP = $_remote_tmp
Add-Type -TypeDefinition $lctype_util
$env:TMP = $original_tmp

Function Get-LastWin32ExceptionMessage {
param([int]$ErrorCode)
$exp = New-Object -TypeName System.ComponentModel.Win32Exception -ArgumentList $ErrorCode
$exp_msg = "{0} (Win32 ErrorCode {1} - 0x{1:X8})" -f $exp.Message, $ErrorCode
return $exp_msg
}

Function Get-SystemLocaleName {
$max_length = 85 # LOCALE_NAME_MAX_LENGTH
$ptr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($max_length)

try {
$res = [Ansible.WinRegion.NativeMethods]::GetSystemDefaultLocaleName($ptr, $max_length)

if ($res -eq 0) {
$err_code = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
$msg = Get-LastWin32ExceptionMessage -Error $err_code
Fail-Json -obj $result -message "Failed to get system locale: $msg"
}

$system_locale = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($ptr)
} finally {
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($ptr)
}

return $system_locale
}

Function Get-UserLocaleName {
$max_length = 85 # LOCALE_NAME_MAX_LENGTH
$ptr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($max_length)

try {
$res = [Ansible.WinRegion.NativeMethods]::GetUserDefaultLocaleName($ptr, $max_length)

if ($res -eq 0) {
$err_code = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
$msg = Get-LastWin32ExceptionMessage -Error $err_code
Fail-Json -obj $result -message "Failed to get user locale: $msg"
}

$user_locale = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($ptr)
} finally {
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($ptr)
}

return $user_locale
}

Function Get-ValidGeoIds($cultures) {
$geo_ids = @()
Expand Down Expand Up @@ -79,20 +150,10 @@ Function Copy-RegistryKey($source, $target) {
}
}

# With the legacy options (needed for OS < Windows 8 and Server 2012) we need to check multiple reg
# keys and modify them if they need changing. This is because Microsoft only made changing these
# values with the newer versions of Windows and didn't backport these features to the older ones,
# thanks a bunch there Microsoft :(
Function Set-CultureLegacy($culture) {
# For when Set-Culture is not available (Pre Windows 8 and Server 2012)
Function Set-UserLocale($culture) {
$reg_key = 'HKCU:\Control Panel\International'

$original_tmp = $env:TMP
$env:TMP = $_remote_tmp
Add-Type -TypeDefinition $lctype_util
$env:TMP = $original_tmp

$lookup = New-Object Ansible.LocaleHelper($culture)
$lookup = New-Object Ansible.WinRegion.LocaleHelper($culture)
# hex values are from http://www.pinvoke.net/default.aspx/kernel32/GetLocaleInfoEx.html
$wanted_values = @{
Locale = '{0:x8}' -f ([System.Globalization.CultureInfo]$culture).LCID
Expand Down Expand Up @@ -257,24 +318,18 @@ if ($null -ne $location) {
}

if ($null -ne $format) {
$current_format = (Get-Culture).Name
# Cannot use Get/Set-Culture as that fails to get and set the culture when running in the PSRP runspace.
$current_format = Get-UserLocaleName
if ($current_format -ne $format) {
# Set-Culture was only added in Server 2012 and above, use legacy option if older
if (Get-Command 'Set-Culture' -ErrorAction SilentlyContinue) {
if (-not $check_mode) {
Set-Culture -CultureInfo $format
}
} else {
Set-CultureLegacy -culture $format
}
Set-UserLocale -culture $format
$result.changed = $true
}
}

if ($null -ne $unicode_language) {
# Get/Set-WinSystemLocale was only added in Server 2012 and above, use legacy option if older
if (Get-Command 'Get-WinSystemLocale' -ErrorAction SilentlyContinue) {
$current_unicode_language = (Get-WinSystemLocale).Name
$current_unicode_language = Get-SystemLocaleName
if ($current_unicode_language -ne $unicode_language) {
if (-not $check_mode) {
Set-WinSystemLocale -SystemLocale $unicode_language
Expand Down