From ad6d78dab01fe23393102e43ab8cd76d0022f1d8 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Fri, 16 Feb 2024 00:52:00 +0800 Subject: [PATCH 1/3] Ensure Windows time zone specs request `SeTimeZonePrivilege` properly --- spec/support/time.cr | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/support/time.cr b/spec/support/time.cr index 80f10f37d8cf..92dcbef1589f 100644 --- a/spec/support/time.cr +++ b/spec/support/time.cr @@ -101,7 +101,8 @@ end ], ) if LibC.AdjustTokenPrivileges(adjust_token, 0, pointerof(new_privileges), 0, nil, nil) != 0 - return true + # ERROR_NOT_ALL_ASSIGNED means the privilege was not adjusted even though the return value is nonzero + return true if WinError.value.error_success? end end From ba138536d64bf94b4e9611201004fc28ed2ed1cc Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Fri, 16 Feb 2024 01:38:09 +0800 Subject: [PATCH 2/3] Update time.cr --- spec/support/time.cr | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/spec/support/time.cr b/spec/support/time.cr index 92dcbef1589f..9b431abb2ada 100644 --- a/spec/support/time.cr +++ b/spec/support/time.cr @@ -56,8 +56,7 @@ end TokenPrivileges = 3 - SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001_u32 - SE_PRIVILEGE_ENABLED = 0x00000002_u32 + SE_PRIVILEGE_ENABLED = 0x00000002_u32 fun OpenProcessToken(processHandle : HANDLE, desiredAccess : DWORD, tokenHandle : HANDLE*) : BOOL fun GetTokenInformation(tokenHandle : HANDLE, tokenInformationClass : Int, tokenInformation : Void*, tokenInformationLength : DWORD, returnLength : DWORD*) : BOOL @@ -78,19 +77,25 @@ end raise RuntimeError.from_winerror("LookupPrivilegeValueW") end + # if the process token already has the privilege, and the privilege is already enabled, + # we don't need to do anything else if LibC.OpenProcessToken(LibC.GetCurrentProcess, LibC::TOKEN_QUERY, out token) != 0 begin LibC.GetTokenInformation(token, LibC::TokenPrivileges, nil, 0, out len) buf = Pointer(UInt8).malloc(len).as(LibC::TOKEN_PRIVILEGES*) LibC.GetTokenInformation(token, LibC::TokenPrivileges, buf, len, out _) privileges = Slice.new(pointerof(buf.value.@privileges).as(LibC::LUID_AND_ATTRIBUTES*), buf.value.privilegeCount) - return true if privileges.any? { |pr| pr.luid == time_zone_luid && pr.attributes & (LibC::SE_PRIVILEGE_ENABLED_BY_DEFAULT | LibC::SE_PRIVILEGE_ENABLED) != 0 } + # if the process token doesn't have the privilege, there is no way + # `AdjustTokenPrivileges` could grant or enable it + privilege = privileges.find(&.luid.== time_zone_luid) + return false unless privilege + return true if privilege.attributes.bits_set?(LibC::SE_PRIVILEGE_ENABLED) ensure LibC.CloseHandle(token) end end - if LibC.OpenProcessToken(LibC.GetCurrentProcess, LibC::TOKEN_ADJUST_PRIVILEGES | LibC::TOKEN_QUERY, out adjust_token) != 0 + if LibC.OpenProcessToken(LibC.GetCurrentProcess, LibC::TOKEN_ADJUST_PRIVILEGES, out adjust_token) != 0 new_privileges = LibC::TOKEN_PRIVILEGES.new( privilegeCount: 1, privileges: StaticArray[ From cbfa4267e1e4c361308045cae6dfae640ac1d323 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Tue, 20 Feb 2024 18:56:43 +0800 Subject: [PATCH 3/3] Update time.cr --- spec/support/time.cr | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/support/time.cr b/spec/support/time.cr index 9b431abb2ada..d550a83af2c3 100644 --- a/spec/support/time.cr +++ b/spec/support/time.cr @@ -106,7 +106,6 @@ end ], ) if LibC.AdjustTokenPrivileges(adjust_token, 0, pointerof(new_privileges), 0, nil, nil) != 0 - # ERROR_NOT_ALL_ASSIGNED means the privilege was not adjusted even though the return value is nonzero return true if WinError.value.error_success? end end