Skip to content

Commit 4a36785

Browse files
authored
Improve initialization warnings. (#271)
1 parent 5ca229f commit 4a36785

File tree

1 file changed

+81
-4
lines changed

1 file changed

+81
-4
lines changed

lib/cl/api.jl

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,85 @@ end
7171

7272
include("libopencl.jl")
7373

74+
@static if Sys.iswindows()
75+
# Windows type aliases
76+
const BOOL = Int32
77+
const DWORD = UInt32
78+
const PDWORD = Ptr{DWORD}
79+
const HANDLE = Ptr{Cvoid}
80+
const PHANDLE = Ptr{HANDLE}
81+
const BYTE = UInt8
82+
const PBYTE = Ptr{BYTE}
83+
const PVOID = Ptr{Cvoid}
84+
const PSID = PVOID
85+
const PSID_AND_ATTRIBUTES = PVOID
86+
struct SID_AND_ATTRIBUTES
87+
Sid::PSID
88+
Attributes::DWORD
89+
end
90+
struct TOKEN_MANDATORY_LABEL
91+
Label::SID_AND_ATTRIBUTES
92+
end
93+
94+
# Windows constants
95+
const TOKEN_QUERY = DWORD(0x0008)
96+
const TOKEN_QUERY_SOURCE = DWORD(0x0010)
97+
const SECURITY_MAX_SID_SIZE = 68
98+
const SECURITY_MANDATORY_MEDIUM_RID = DWORD(0x2000)
99+
const TokenIntegrityLevel = 25 # TOKEN_INFORMATION_CLASS enum value
100+
101+
const kernel32 = "kernel32.dll"
102+
GetCurrentProcess() = @ccall kernel32.GetCurrentProcess()::HANDLE
103+
CloseHandle(hObject) = @ccall kernel32.CloseHandle(hObject::HANDLE)::BOOL
104+
105+
const advapi32 = "advapi32.dll"
106+
OpenProcessToken(ProcessHandle, DesiredAccess, TokenHandle) =
107+
@ccall advapi32.OpenProcessToken(ProcessHandle::HANDLE, DesiredAccess::DWORD, TokenHandle::PHANDLE)::BOOL
108+
GetTokenInformation(TokenHandle, TokenInformationClass, TokenInformation, TokenInformationLength, ReturnLength) =
109+
@ccall advapi32.GetTokenInformation(TokenHandle::HANDLE, TokenInformationClass::Int32, TokenInformation::PBYTE, TokenInformationLength::DWORD, ReturnLength::PDWORD)::BOOL
110+
GetSidSubAuthorityCount(pSid) =
111+
@ccall advapi32.GetSidSubAuthorityCount(pSid::PSID)::PBYTE
112+
GetSidSubAuthority(pSid, nSubAuthority) =
113+
@ccall advapi32.GetSidSubAuthority(pSid::PSID, nSubAuthority::DWORD)::PDWORD
114+
115+
# mimics `khrIcd_IsHighIntegrityLevel`, which determines if we can specify
116+
# drivers through environment variables
117+
function is_high_integrity_level()::Bool
118+
is_high_integrity = false
119+
120+
h_token = Ref{HANDLE}()
121+
if OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_QUERY_SOURCE, h_token) != 0
122+
try
123+
# Maximum possible size of SID_AND_ATTRIBUTES is maximum size of a SID + size of attributes DWORD.
124+
mandatory_label_buffer = zeros(BYTE, SECURITY_MAX_SID_SIZE + sizeof(DWORD))
125+
buffer_size = Ref{DWORD}()
126+
if GetTokenInformation(h_token[], TokenIntegrityLevel, mandatory_label_buffer, length(mandatory_label_buffer), buffer_size) != 0
127+
mandatory_label = unsafe_load(Ptr{TOKEN_MANDATORY_LABEL}(pointer(mandatory_label_buffer)))
128+
sub_auth_count = unsafe_load(GetSidSubAuthorityCount(mandatory_label.Label.Sid))
129+
integrity_level = unsafe_load(GetSidSubAuthority(mandatory_label.Label.Sid, sub_auth_count - 1))
130+
131+
return integrity_level > SECURITY_MANDATORY_MEDIUM_RID
132+
end
133+
finally
134+
CloseHandle(h_token[])
135+
end
136+
end
137+
138+
return is_high_integrity
139+
end
140+
end
141+
74142
# lazy initialization
75143
const initialized = Ref{Bool}(false)
76144
@noinline function initialize()
77145
initialized[] = true
78146

79-
if isempty(OpenCL_jll.drivers)
80-
@warn """No OpenCL driver JLLs were detected at the time of the first call into OpenCL.jl.
81-
Only system drivers will be available."""
82-
return
147+
@static if Sys.iswindows()
148+
if is_high_integrity_level()
149+
@warn """Running at high integrity level, preventing OpenCL.jl from loading drivers from JLLs.
150+
151+
Only system drivers will be available. To enable JLL drivers, do not run Julia as an administrator."""
152+
end
83153
end
84154

85155
ocd_filenames = join(OpenCL_jll.drivers, ':')
@@ -92,6 +162,13 @@ const initialized = Ref{Bool}(false)
92162
@ccall libopencl.clGetPlatformIDs(
93163
0::cl_uint, C_NULL::Ptr{cl_platform_id},
94164
num_platforms::Ptr{cl_uint})::cl_int
165+
166+
if num_platforms[] == 0 && isempty(OpenCL_jll.drivers)
167+
@error """No OpenCL drivers available, either system-wide or provided by a JLL.
168+
169+
Please install a system-wide OpenCL driver, or load one together with OpenCL.jl,
170+
e.g., by doing `using OpenCL, pocl_jll`."""
171+
end
95172
end
96173
end
97174

0 commit comments

Comments
 (0)