diff options
Diffstat (limited to 'systems/texlive/tlnet/tlpkg/tlperl/lib/Win32.pm')
-rw-r--r-- | systems/texlive/tlnet/tlpkg/tlperl/lib/Win32.pm | 353 |
1 files changed, 264 insertions, 89 deletions
diff --git a/systems/texlive/tlnet/tlpkg/tlperl/lib/Win32.pm b/systems/texlive/tlnet/tlpkg/tlperl/lib/Win32.pm index 5a197e9e9e..1092c5ab52 100644 --- a/systems/texlive/tlnet/tlpkg/tlperl/lib/Win32.pm +++ b/systems/texlive/tlnet/tlpkg/tlperl/lib/Win32.pm @@ -8,7 +8,7 @@ package Win32; require DynaLoader; @ISA = qw|Exporter DynaLoader|; - $VERSION = '0.53'; + $VERSION = '0.57'; $XS_VERSION = $VERSION; $VERSION = eval $VERSION; @@ -174,6 +174,7 @@ sub VER_SUITE_STORAGE_SERVER () { 0x00002000 } # Windows Storage Serve sub VER_SUITE_TERMINAL () { 0x00000010 } # Terminal Services is installed. This value is always set. # If VER_SUITE_TERMINAL is set but VER_SUITE_SINGLEUSERTS is not set, the system is running in application server mode. sub VER_SUITE_WH_SERVER () { 0x00008000 } # Windows Home Server is installed. +sub VER_SUITE_MULTIUSERTS () { 0x00020000 } # AppServer mode is enabled. sub SM_TABLETPC () { 86 } @@ -359,7 +360,8 @@ sub GetOSDisplayName { $desc =~ s/^\s*//; s/(200.)/$name Server $1/; } - s/^Windows (20(03|08|12))/Windows Server $1/; + s/^Windows (20(03|08|12|16|19))/Windows Server $1/; + s/^Windows SAC/Windows Server/; } } $name .= " $desc" if length $desc; @@ -528,12 +530,12 @@ sub _GetOSName { } } elsif ($minor == 2) { - if ($producttype == VER_NT_WORKSTATION) { - $os = "8"; - } - else { - $os = "2012"; - } + if ($producttype == VER_NT_WORKSTATION) { + $os = "8"; + } + else { + $os = "2012"; + } } elsif ($minor == 3) { if ($producttype == VER_NT_WORKSTATION) { @@ -546,64 +548,130 @@ sub _GetOSName { } } elsif ($major == 10) { - $os = '10'; + if ($producttype == VER_NT_WORKSTATION) { + # Build numbers from https://en.wikipedia.org/wiki/Windows_10_version_history + $os = '10'; + if (9841 <= $build && $build <= 10240) { + $desc = " Version 1507"; + $desc .= " (Preview Build $build)" if $build < 10240; + $desc .= " (RTM)" if $build == 10240; + } + elsif (10525 <= $build && $build <= 10586) { + $desc = " Version 1511 (November Update)"; + $desc .= " (Preview Build $build)" if $build < 10586; + } + elsif (11082 <= $build && $build <= 14393) { + $desc = " Version 1607 (Anniversary Update)"; + $desc .= " (Preview Build $build)" if $build < 14393; + } + elsif (14901 <= $build && $build <= 15063) { + $desc = " Version 1703 (Creators Update)"; + $desc .= " (Preview Build $build)" if $build < 15063; + } + elsif (16170 <= $build && $build <= 16299) { + $desc = " Version 1709 (Fall Creators Update)"; + $desc .= " (Preview Build $build)" if $build < 16299; + } + elsif (16353 <= $build && $build <= 17134) { + $desc = " Version 1803 (April 2018 Update)"; + $desc .= " (Preview Build $build)" if $build < 17134; + } + elsif (17604 <= $build && $build <= 17763) { + $desc = " Version 1809 (October 2018 Update)"; + $desc .= " (Preview Build $build)" if $build < 17763; + } + elsif (18204 <= $build && $build <= 18362) { + $desc = " Version 1903 (May 2019 Update)"; + $desc .= " (Preview Build $build)" if $build < 18362; + } + else { + $desc = " Build $build"; + } + } + else { + if ($build == 14393) { + $os = "2016"; + $desc = "Version 1607"; + } + elsif ($build == 17763) { + $os = "2019"; + $desc = "Version 1809"; + } + else { + $os = "Server"; + if ($build == 16299) { + $desc = "Version 1709"; + } + elsif ($build == 17134) { + $desc = "Version 1803"; + } + elsif ($build == 18362) { + $desc = "Version 1903"; + } + else { + $desc = "Build $build"; + } + } + } } if ($major >= 6) { - if ($productinfo == PRODUCT_ULTIMATE) { - $desc .= " Ultimate"; - } - elsif ($productinfo == PRODUCT_HOME_PREMIUM) { - $desc .= " Home Premium"; - } - elsif ($productinfo == PRODUCT_HOME_BASIC) { - $desc .= " Home Basic"; - } - elsif ($productinfo == PRODUCT_ENTERPRISE) { - $desc .= " Enterprise"; - } - elsif ($productinfo == PRODUCT_BUSINESS) { - # "Windows 7 Business" had a name change to "Windows 7 Professional" - $desc .= $minor == 0 ? " Business" : " Professional"; - } - elsif ($productinfo == PRODUCT_STARTER) { - $desc .= " Starter"; - } - elsif ($productinfo == PRODUCT_CLUSTER_SERVER) { - $desc .= " HPC Server"; - } - elsif ($productinfo == PRODUCT_DATACENTER_SERVER) { - $desc .= " Datacenter"; - } - elsif ($productinfo == PRODUCT_DATACENTER_SERVER_CORE) { - $desc .= " Datacenter Edition (core installation)"; - } - elsif ($productinfo == PRODUCT_ENTERPRISE_SERVER) { - $desc .= " Enterprise"; - } - elsif ($productinfo == PRODUCT_ENTERPRISE_SERVER_CORE) { - $desc .= " Enterprise Edition (core installation)"; - } - elsif ($productinfo == PRODUCT_ENTERPRISE_SERVER_IA64) { - $desc .= " Enterprise Edition for Itanium-based Systems"; - } - elsif ($productinfo == PRODUCT_SMALLBUSINESS_SERVER) { - $desc .= " Small Business Server"; - } - elsif ($productinfo == PRODUCT_SMALLBUSINESS_SERVER_PREMIUM) { - $desc .= " Small Business Server Premium Edition"; - } - elsif ($productinfo == PRODUCT_STANDARD_SERVER) { - $desc .= " Standard"; - } - elsif ($productinfo == PRODUCT_STANDARD_SERVER_CORE) { - $desc .= " Standard Edition (core installation)"; - } - elsif ($productinfo == PRODUCT_WEB_SERVER) { - $desc .= " Web Server"; - } - elsif ($productinfo == PRODUCT_PROFESSIONAL) { - $desc .= " Professional"; + if ($major == 6) { + if ($productinfo == PRODUCT_ULTIMATE) { + $desc .= " Ultimate"; + } + elsif ($productinfo == PRODUCT_HOME_PREMIUM) { + $desc .= " Home Premium"; + } + elsif ($productinfo == PRODUCT_HOME_BASIC) { + $desc .= " Home Basic"; + } + elsif ($productinfo == PRODUCT_ENTERPRISE) { + $desc .= " Enterprise"; + } + elsif ($productinfo == PRODUCT_BUSINESS) { + # "Windows 7 Business" had a name change to "Windows 7 Professional" + $desc .= $minor == 0 ? " Business" : " Professional"; + } + elsif ($productinfo == PRODUCT_STARTER) { + $desc .= " Starter"; + } + elsif ($productinfo == PRODUCT_CLUSTER_SERVER) { + $desc .= " HPC Server"; + } + elsif ($productinfo == PRODUCT_DATACENTER_SERVER) { + $desc .= " Datacenter"; + } + elsif ($productinfo == PRODUCT_DATACENTER_SERVER_CORE) { + $desc .= " Datacenter Edition (core installation)"; + } + elsif ($productinfo == PRODUCT_ENTERPRISE_SERVER) { + $desc .= " Enterprise"; + } + elsif ($productinfo == PRODUCT_ENTERPRISE_SERVER_CORE) { + $desc .= " Enterprise Edition (core installation)"; + } + elsif ($productinfo == PRODUCT_ENTERPRISE_SERVER_IA64) { + $desc .= " Enterprise Edition for Itanium-based Systems"; + } + elsif ($productinfo == PRODUCT_SMALLBUSINESS_SERVER) { + $desc .= " Small Business Server"; + } + elsif ($productinfo == PRODUCT_SMALLBUSINESS_SERVER_PREMIUM) { + $desc .= " Small Business Server Premium Edition"; + } + elsif ($productinfo == PRODUCT_STANDARD_SERVER) { + $desc .= " Standard"; + } + elsif ($productinfo == PRODUCT_STANDARD_SERVER_CORE) { + $desc .= " Standard Edition (core installation)"; + } + elsif ($productinfo == PRODUCT_WEB_SERVER) { + $desc .= " Web Server"; + } + elsif ($productinfo == PRODUCT_PROFESSIONAL) { + $desc .= " Professional"; + } } if ($arch == PROCESSOR_ARCHITECTURE_INTEL) { @@ -612,7 +680,7 @@ sub _GetOSName { elsif ($arch == PROCESSOR_ARCHITECTURE_AMD64) { $desc .= " (64-bit)"; } - } + } } unless (defined $os) { @@ -645,6 +713,27 @@ sub _GetOSName { return ("Win$os", $desc); } +sub IsSymlinkCreationAllowed { + my(undef, $major, $minor, $build) = GetOSVersion(); + + # Vista was the first Windows version with symlink support + return !!0 if $major < 6; + + # Since Windows 10 1703, enabling the developer mode allows to create + # symlinks regardless of process privileges + if ($major > 10 || ($major == 10 && ($minor > 0 || $build > 15063))) { + return !!1 if IsDeveloperModeEnabled(); + } + + my $privs = GetProcessPrivileges(); + + return !!0 unless $privs; + + # It doesn't matter if the permission is enabled or not, it just has to + # exist. CreateSymbolicLink() will automatically enable it when needed. + return exists $privs->{SeCreateSymbolicLinkPrivilege}; +} + # "no warnings 'redefine';" doesn't work for 5.8.7 and earlier local $^W = 0; bootstrap Win32; @@ -998,6 +1087,10 @@ GetOSVersion() in list context. The description will also include tags for other special editions, like "R2", "Media Center", "Tablet PC", or "Starter Edition". +In the Windows 10 / Server Semi-Annual Channel era, the description may +contain the relevant ReleaseId value, but this is only inferred from +the build number, not determined absolutely. + Currently the possible values for the OS name are WinWin32s @@ -1013,6 +1106,12 @@ Currently the possible values for the OS name are WinVista Win2008 Win7 + Win8 + Win8.1 + Win10 + Win2016 + Win2019 + WinSAC This routine is just a simple interface into GetOSVersion(). More specific or demanding situations should use that instead. Another @@ -1038,30 +1137,36 @@ For the ID, the values are 0 for Win32s, 1 for Windows 9X/Me and 2 for Windows NT/2000/XP/2003/Vista/2008/7. In scalar context it returns just the ID. -Currently known values for ID MAJOR and MINOR are as follows: - - OS ID MAJOR MINOR - Win32s 0 - - - Windows 95 1 4 0 - Windows 98 1 4 10 - Windows Me 1 4 90 - - Windows NT 3.51 2 3 51 - Windows NT 4 2 4 0 - - Windows 2000 2 5 0 - Windows XP 2 5 1 - Windows Server 2003 2 5 2 - Windows Server 2003 R2 2 5 2 - Windows Home Server 2 5 2 - - Windows Vista 2 6 0 - Windows Server 2008 2 6 0 - Windows 7 2 6 1 - Windows Server 2008 R2 2 6 1 - Windows 8 2 6 2 - Windows Server 2012 2 6 2 - +Currently known values for ID MAJOR MINOR and BUILD are as follows: + + OS ID MAJOR MINOR BUILD + Win32s 0 - - - + Windows 95 1 4 0 - + Windows 98 1 4 10 - + Windows Me 1 4 90 - + + Windows NT 3.51 2 3 51 - + Windows NT 4 2 4 0 - + + Windows 2000 2 5 0 - + Windows XP 2 5 1 - + Windows Server 2003 2 5 2 - + Windows Server 2003 R2 2 5 2 - + Windows Home Server 2 5 2 - + + Windows Vista 2 6 0 - + Windows Server 2008 2 6 0 - + Windows 7 2 6 1 - + Windows Server 2008 R2 2 6 1 - + Windows 8 2 6 2 - + Windows Server 2012 2 6 2 - + Windows 8.1 2 6 2 - + Windows Server 2012 R2 2 6 2 - + + Windows 10 2 10 0 - + Windows Server 2016 2 10 0 14393 + Windows Server 2019 2 10 0 17677 + On Windows NT 4 SP6 and later this function returns the following additional values: SPMAJOR, SPMINOR, SUITEMASK, PRODUCTTYPE. @@ -1081,8 +1186,14 @@ The version numbers for Windows 8 and Windows Server 2012 are identical; the PRODUCTTYPE field must be used to differentiate between them. +For modern Windows releases, the major and minor version numbers are +identical. The PRODUCTTYPE field must be used to differentiate between +Windows 10 and Server releases. The BUILD field is used to +differentiate Windows Server versions: currently 2016, 2019, and +Semi-Annual Channel releases. + SPMAJOR and SPMINOR are the version numbers of the latest -installed service pack. +installed service pack. (In the Windows 10 era, these are unused.) SUITEMASK is a bitfield identifying the product suites available on the system. Known bits are: @@ -1103,6 +1214,7 @@ the system. Known bits are: VER_SUITE_STORAGE_SERVER 0x00002000 VER_SUITE_COMPUTE_SERVER 0x00004000 VER_SUITE_WH_SERVER 0x00008000 + VER_SUITE_MULTIUSERTS 0x00020000 The VER_SUITE_xxx names are listed here to cross reference the Microsoft documentation. The Win32 module does not provide symbolic names for these @@ -1142,6 +1254,25 @@ information about what you can do with this address has been lost in the mist of time. Use the Win32::API module instead of this deprecated function. +=item Win32::GetProcessPrivileges([PID]) + +Returns a reference to a hash holding the information about the privileges +held by the specified process. The keys are privilege names, and the values +are booleans indicating whether a given privilege is currently enabled or not. + +If the optional PID parameter is omitted, the function queries the current +process. + +Example return value: + + { + SeTimeZonePrivilege => 0, + SeShutdownPrivilege => 0, + SeUndockPrivilege => 0, + SeIncreaseWorkingSetPrivilege => 0, + SeChangeNotifyPrivilege => 1 + } + =item Win32::GetProductInfo(OSMAJOR, OSMINOR, SPMAJOR, SPMINOR) Retrieves the product type for the operating system on the local @@ -1194,6 +1325,17 @@ actually running with elevated privileges. Returns C<undef> and prints a warning if an error occurred. This function always returns 1 on Win9X. +=item Win32::IsDeveloperModeEnabled() + +Returns true if the developer mode is currently enabled. It always returns +false on Windows versions older than Windows 10. + +=item Win32::IsSymlinkCreationAllowed() + +Returns true if the current process is allowed to create symbolic links. This +function is a convenience wrapper around Win32::GetProcessPrivileges() and +Win32::IsDeveloperModeEnabled(). + =item Win32::IsWinNT() [CORE] Returns non zero if the Win32 subsystem is Windows NT. @@ -1332,4 +1474,37 @@ DllUnregisterServer. =back +=head1 CAVEATS + +=head2 Short Path Names + +There are many situations in which modern Windows systems will not have +the L<short path name|https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#short-vs-long-names> +(also called 8.3 or MS-DOS) alias for long file names available. + +Short path support can be configured system-wide via the registry, +but the default on modern systems is to configure short path usage per +volume. The configuration for a volume can be queried in a number of ways, +but these may either be unreliable or require elevated (administrator) +privileges. + +Typically, the configuration for a volume can be queried using the C<fsutil> +utility, e.g. C<fsutil 8dot3name query d:>. On the C level, it can be queried +with a C<FSCTL_QUERY_PERSISTENT_VOLUME_STATE> request to the +C<DeviceIOControl> API call, as described in +L<this article|https://www.codeproject.com/Articles/304374/Query-Volume-Setting-for-State-Windows>. +However, both of these methods require administrator privileges to work. + +The Win32 module does not perform any per-volume check and simply fetches +short path names in the same manner as the underlying Windows API call it +uses: If short path names are disabled, the call will still succeed but the +long name will actually be returned. + +Note that on volumes where this happens, C<GetANSIPathName> usually cannot be +used to return useful filenames for files that contain unicode characters. +(In code page 65001, this may still work.) Handling unicode filenames in this +legacy manner relies upon C<GetShortPathName> returning 8.3 filenames, but +without short name support, it will return the filename with all unicode +characters replaced by question mark characters. + =cut |