summaryrefslogtreecommitdiff
path: root/systems/texlive/tlnet/tlpkg/tlperl/lib/Win32.pm
diff options
context:
space:
mode:
Diffstat (limited to 'systems/texlive/tlnet/tlpkg/tlperl/lib/Win32.pm')
-rw-r--r--systems/texlive/tlnet/tlpkg/tlperl/lib/Win32.pm353
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