Merge pull request #10 from KhronosGroup/master
added checks for high integrity for Windows secure_getenv
diff --git a/README.md b/README.md
index ee8499a..099f3a6 100644
--- a/README.md
+++ b/README.md
@@ -31,6 +31,11 @@
By default, the OpenCL ICD Loader will look for OpenCL Headers in the `inc` directory.
By default, the OpenCL ICD Loader on Windows requires the Windows Driver Kit (WDK).
+To build OpenCL ICD Loader with WDK support -
+* Install recent Windows WDK currently at https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk
+
+* Establish environment variable WDK to include directory. Ex: set WDK=C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0
+
An OpenCL ICD Loader may be built without the Windows Driver Kit using the CMake variable `OPENCL_ICD_LOADER_REQUIRE_WDK`, however this option should be used with caution since it may prevent the OpenCL ICD Loader from enumerating some OpenCL implementations.
This dependency may be removed in the future.
diff --git a/loader/linux/icd_linux.c b/loader/linux/icd_linux.c
index f6ae790..809f095 100644
--- a/loader/linux/icd_linux.c
+++ b/loader/linux/icd_linux.c
@@ -172,4 +172,3 @@
{
dlclose(library);
}
-
diff --git a/loader/windows/icd_windows.c b/loader/windows/icd_windows.c
index 9c87817..f1609e8 100644
--- a/loader/windows/icd_windows.c
+++ b/loader/windows/icd_windows.c
@@ -23,8 +23,77 @@
#include <windows.h>
#include <winreg.h>
+#include <initguid.h>
+#include <dxgi.h>
+typedef HRESULT (WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID, void **);
+
static INIT_ONCE initialized = INIT_ONCE_STATIC_INIT;
+typedef struct WinAdapter
+{
+ char * szName;
+ LUID luid;
+} WinAdapter;
+
+const LUID ZeroLuid = { 0, 0 };
+
+static WinAdapter* pWinAdapterBegin = NULL;
+static WinAdapter* pWinAdapterEnd = NULL;
+static WinAdapter* pWinAdapterCapacity = NULL;
+
+BOOL adapterAdd(const char* szName, LUID luid)
+{
+ BOOL result = TRUE;
+ if (pWinAdapterEnd == pWinAdapterCapacity)
+ {
+ size_t oldCapacity = pWinAdapterCapacity - pWinAdapterBegin;
+ size_t newCapacity = oldCapacity;
+ if (0 == newCapacity)
+ {
+ newCapacity = 1;
+ }
+ else if(newCapacity < UINT_MAX/2)
+ {
+ newCapacity *= 2;
+ }
+
+ WinAdapter* pNewBegin = malloc(newCapacity * sizeof(*pWinAdapterBegin));
+ if (!pNewBegin)
+ result = FALSE;
+ else
+ {
+ if (pWinAdapterBegin)
+ {
+ memcpy(pNewBegin, pWinAdapterBegin, oldCapacity * sizeof(*pWinAdapterBegin));
+ free(pWinAdapterBegin);
+ }
+ pWinAdapterCapacity = pNewBegin + newCapacity;
+ pWinAdapterEnd = pNewBegin + oldCapacity;
+ pWinAdapterBegin = pNewBegin;
+ }
+ }
+ if (pWinAdapterEnd != pWinAdapterCapacity)
+ {
+ size_t nameLen = (strlen(szName) + 1)*sizeof(szName[0]);
+ pWinAdapterEnd->szName = malloc(nameLen);
+ if (!pWinAdapterEnd->szName)
+ result = FALSE;
+ else
+ {
+ memcpy(pWinAdapterEnd->szName, szName, nameLen);
+ pWinAdapterEnd->luid = luid;
+ ++pWinAdapterEnd;
+ }
+ }
+ return result;
+}
+
+void adapterFree(WinAdapter *pWinAdapter)
+{
+ free(pWinAdapter->szName);
+ pWinAdapter->szName = NULL;
+}
+
/*
*
* Vendor enumeration functions
@@ -36,6 +105,7 @@
BOOL CALLBACK khrIcdOsVendorsEnumerate(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContext)
{
LONG result;
+ BOOL status = FALSE;
const char* platformsName = "SOFTWARE\\Khronos\\OpenCL\\Vendors";
HKEY platformsKey = NULL;
DWORD dwIndex;
@@ -103,19 +173,63 @@
KHR_ICD_TRACE("Value not zero, skipping\n");
continue;
}
-
// add the library
- khrIcdVendorAdd(cszLibraryName);
- }
-
- result = RegCloseKey(platformsKey);
- if (ERROR_SUCCESS != result)
- {
- KHR_ICD_TRACE("Failed to close platforms key %s, ignoring\n", platformsName);
+ status |= adapterAdd(cszLibraryName, ZeroLuid);
}
}
- return TRUE;
+ // Add adapters according to DXGI's preference order
+ HMODULE hDXGI = LoadLibrary("dxgi.dll");
+ if (hDXGI)
+ {
+ IDXGIFactory* pFactory = NULL;
+ PFN_CREATE_DXGI_FACTORY pCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY)GetProcAddress(hDXGI, "CreateDXGIFactory");
+ if (pCreateDXGIFactory)
+ {
+ HRESULT hr = pCreateDXGIFactory(&IID_IDXGIFactory, &pFactory);
+ if (SUCCEEDED(hr))
+ {
+ UINT i = 0;
+ IDXGIAdapter* pAdapter = NULL;
+ while (SUCCEEDED(pFactory->lpVtbl->EnumAdapters(pFactory, i++, &pAdapter)))
+ {
+ DXGI_ADAPTER_DESC AdapterDesc;
+ if (SUCCEEDED(pAdapter->lpVtbl->GetDesc(pAdapter, &AdapterDesc)))
+ {
+ for (WinAdapter* iterAdapter = pWinAdapterBegin; iterAdapter != pWinAdapterEnd; ++iterAdapter)
+ {
+ if (iterAdapter->luid.LowPart == AdapterDesc.AdapterLuid.LowPart
+ && iterAdapter->luid.HighPart == AdapterDesc.AdapterLuid.HighPart)
+ {
+ khrIcdVendorAdd(iterAdapter->szName);
+ break;
+ }
+ }
+ }
+
+ pAdapter->lpVtbl->Release(pAdapter);
+ }
+ pFactory->lpVtbl->Release(pFactory);
+ }
+ FreeLibrary(hDXGI);
+ }
+ }
+
+ // Go through the list again, putting any remaining adapters at the end of the list in an undefined order
+ for (WinAdapter* iterAdapter = pWinAdapterBegin; iterAdapter != pWinAdapterEnd; ++iterAdapter)
+ {
+ khrIcdVendorAdd(iterAdapter->szName);
+ adapterFree(iterAdapter);
+ }
+
+ free(pWinAdapterBegin);
+
+ result = RegCloseKey(platformsKey);
+ if (ERROR_SUCCESS != result)
+ {
+ KHR_ICD_TRACE("Failed to close platforms key %s, ignoring\n", platformsName);
+ }
+ return status;
}
// go through the list of vendors only once
@@ -151,4 +265,3 @@
{
FreeLibrary( (HMODULE)library);
}
-
diff --git a/loader/windows/icd_windows_dxgk.c b/loader/windows/icd_windows_dxgk.c
index 8cc3fb9..c55cbf7 100644
--- a/loader/windows/icd_windows_dxgk.c
+++ b/loader/windows/icd_windows_dxgk.c
@@ -35,18 +35,23 @@
bool khrIcdOsVendorsEnumerateDXGK(void)
{
bool ret = false;
+ int result = 0;
#if defined(OPENCL_ICD_LOADER_REQUIRE_WDK)
#if defined(DXGKDDI_INTERFACE_VERSION_WDDM2_4) && (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_4)
+ // Get handle to GDI Runtime
+ HMODULE h = LoadLibrary("gdi32.dll");
+ if (h == NULL)
+ return ret;
+
+ if(GetProcAddress((HMODULE)h, "D3DKMTSubmitPresentBltToHwQueue")) // OS Version check
{
D3DKMT_ADAPTERINFO* pAdapterInfo = NULL;
D3DKMT_ENUMADAPTERS2 EnumAdapters;
NTSTATUS Status = STATUS_SUCCESS;
- // Get handle to GDI Runtime
- HMODULE h = LoadLibrary("gdi32.dll");
- KHR_ICD_ASSERT(h != NULL);
-
char cszLibraryName[MAX_PATH] = { 0 };
+ EnumAdapters.NumAdapters = 0;
+ EnumAdapters.pAdapters = NULL;
PFND3DKMT_ENUMADAPTERS2 pEnumAdapters2 = (PFND3DKMT_ENUMADAPTERS2)GetProcAddress((HMODULE)h, "D3DKMTEnumAdapters2");
if (!pEnumAdapters2)
{
@@ -83,47 +88,50 @@
KHR_ICD_TRACE("D3DKMT_ENUMADAPTERS2 status != SUCCESS\n");
goto out;
}
+ const char* cszOpenCLRegKeyName = getOpenCLRegKeyName();
+ const int szOpenCLRegKeyName = (int)(strlen(cszOpenCLRegKeyName) + 1)*sizeof(cszOpenCLRegKeyName[0]);
for (UINT AdapterIndex = 0; AdapterIndex < EnumAdapters.NumAdapters; AdapterIndex++)
{
- D3DDDI_QUERYREGISTRY_INFO QueryArgs = {0};
- D3DDDI_QUERYREGISTRY_INFO* pQueryArgs = &QueryArgs;
+ D3DDDI_QUERYREGISTRY_INFO queryArgs = {0};
+ D3DDDI_QUERYREGISTRY_INFO* pQueryArgs = &queryArgs;
D3DDDI_QUERYREGISTRY_INFO* pQueryBuffer = NULL;
- QueryArgs.QueryType = D3DDDI_QUERYREGISTRY_ADAPTERKEY;
- QueryArgs.QueryFlags.TranslatePath = TRUE;
- QueryArgs.ValueType = REG_SZ;
-#ifdef _WIN64
- wcscpy_s(QueryArgs.ValueName, ARRAYSIZE(L"OpenCLDriverName"), L"OpenCLDriverName");
-#else
- // There is no WOW prefix for 32bit Windows hence make a specific check
- BOOL is_wow64;
- if (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)
- {
- wcscpy_s(QueryArgs.ValueName, ARRAYSIZE(L"OpenCLDriverNameWow"), L"OpenCLDriverNameWow");
- }
- else
- {
- wcscpy_s(QueryArgs.ValueName, ARRAYSIZE(L"OpenCLDriverName"), L"OpenCLDriverName");
- }
-#endif
- D3DKMT_QUERYADAPTERINFO QueryAdapterInfo = {0};
- QueryAdapterInfo.hAdapter = pAdapterInfo[AdapterIndex].hAdapter;
- QueryAdapterInfo.Type = KMTQAITYPE_QUERYREGISTRY;
- QueryAdapterInfo.pPrivateDriverData = &QueryArgs;
- QueryAdapterInfo.PrivateDriverDataSize = sizeof(QueryArgs);
- Status = D3DKMTQueryAdapterInfo(&QueryAdapterInfo);
+ queryArgs.QueryType = D3DDDI_QUERYREGISTRY_ADAPTERKEY;
+ queryArgs.QueryFlags.TranslatePath = TRUE;
+ queryArgs.ValueType = REG_SZ;
+ result = MultiByteToWideChar(
+ CP_ACP,
+ 0,
+ cszOpenCLRegKeyName,
+ szOpenCLRegKeyName,
+ queryArgs.ValueName,
+ ARRAYSIZE(queryArgs.ValueName));
+ if (!result)
+ {
+ KHR_ICD_TRACE("MultiByteToWideChar status != SUCCESS\n");
+ continue;
+ }
+ D3DKMT_QUERYADAPTERINFO queryAdapterInfo = {0};
+ queryAdapterInfo.hAdapter = pAdapterInfo[AdapterIndex].hAdapter;
+ queryAdapterInfo.Type = KMTQAITYPE_QUERYREGISTRY;
+ queryAdapterInfo.pPrivateDriverData = &queryArgs;
+ queryAdapterInfo.PrivateDriverDataSize = sizeof(queryArgs);
+ Status = D3DKMTQueryAdapterInfo(&queryAdapterInfo);
if (!NT_SUCCESS(Status))
{
- KHR_ICD_TRACE("D3DKMT_QUERYADAPTERINFO status != SUCCESS\n");
- goto out;
+ // Continue trying to get as much info on each adapter as possible.
+ // It's too late to return FALSE and claim WDDM2_4 enumeration is not available here.
+ continue;
}
if (NT_SUCCESS(Status) && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_BUFFER_OVERFLOW)
{
- ULONG QueryBufferSize = sizeof(D3DDDI_QUERYREGISTRY_INFO) + QueryArgs.OutputValueSize;
- pQueryBuffer = (D3DDDI_QUERYREGISTRY_INFO*)malloc(QueryBufferSize);
- memcpy(pQueryBuffer, &QueryArgs, sizeof(D3DDDI_QUERYREGISTRY_INFO));
- QueryAdapterInfo.pPrivateDriverData = pQueryBuffer;
- QueryAdapterInfo.PrivateDriverDataSize = QueryBufferSize;
- Status = D3DKMTQueryAdapterInfo(&QueryAdapterInfo);
+ ULONG queryBufferSize = sizeof(D3DDDI_QUERYREGISTRY_INFO) + queryArgs.OutputValueSize;
+ pQueryBuffer = (D3DDDI_QUERYREGISTRY_INFO*)malloc(queryBufferSize);
+ if (pQueryBuffer == NULL)
+ continue;
+ memcpy(pQueryBuffer, &queryArgs, sizeof(D3DDDI_QUERYREGISTRY_INFO));
+ queryAdapterInfo.pPrivateDriverData = pQueryBuffer;
+ queryAdapterInfo.PrivateDriverDataSize = queryBufferSize;
+ Status = D3DKMTQueryAdapterInfo(&queryAdapterInfo);
pQueryArgs = pQueryBuffer;
}
if (NT_SUCCESS(Status) && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_SUCCESS)
@@ -133,7 +141,7 @@
{
size_t len = wcstombs(cszLibraryName, pWchar, sizeof(cszLibraryName));
KHR_ICD_ASSERT(len == (sizeof(cszLibraryName) - 1));
- khrIcdVendorAdd(cszLibraryName);
+ ret |= adapterAdd(cszLibraryName, pAdapterInfo[AdapterIndex].AdapterLuid);
}
}
else if (Status == STATUS_INVALID_PARAMETER && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_FAIL)
@@ -143,11 +151,12 @@
}
free(pQueryBuffer);
}
- ret = true;
out:
free(pAdapterInfo);
- FreeLibrary(h);
}
+
+ FreeLibrary(h);
+
#endif
#endif
return ret;
diff --git a/loader/windows/icd_windows_hkr.c b/loader/windows/icd_windows_hkr.c
index 3387181..a323312 100644
--- a/loader/windows/icd_windows_hkr.c
+++ b/loader/windows/icd_windows_hkr.c
@@ -19,6 +19,7 @@
#include "icd.h"
#include "icd_windows_hkr.h"
#include <windows.h>
+#include "icd_windows_dxgk.h"
#include <cfgmgr32.h>
#include <assert.h>
#include <stdbool.h>
@@ -51,7 +52,7 @@
#endif
// Do not free the memory returned by this function.
-static const char* GetOpenCLRegKeyName(void)
+const char* getOpenCLRegKeyName(void)
{
#ifdef _WIN64
return OPENCL_REG_SUB_KEY;
@@ -96,7 +97,7 @@
{
result = RegQueryValueExA(
hkey,
- GetOpenCLRegKeyName(),
+ getOpenCLRegKeyName(),
NULL,
&dwLibraryNameType,
NULL,
@@ -117,7 +118,7 @@
result = RegQueryValueExA(
hkey,
- GetOpenCLRegKeyName(),
+ getOpenCLRegKeyName(),
NULL,
&dwLibraryNameType,
(LPBYTE)cszOclPath,
@@ -136,9 +137,7 @@
KHR_ICD_TRACE(" Path: %s\n", cszOclPath);
- khrIcdVendorAdd(cszOclPath);
-
- bRet = true;
+ bRet |= adapterAdd(cszOclPath, ZeroLuid);
}
out:
diff --git a/loader/windows/icd_windows_hkr.h b/loader/windows/icd_windows_hkr.h
index 698fe5a..039da05 100644
--- a/loader/windows/icd_windows_hkr.h
+++ b/loader/windows/icd_windows_hkr.h
@@ -17,5 +17,13 @@
*/
#include <stdbool.h>
+#include <windows.h>
bool khrIcdOsVendorsEnumerateHKR(void);
+
+extern const LUID ZeroLuid;
+
+BOOL adapterAdd(const char* szName, LUID luid);
+
+// Do not free the memory returned by this function.
+const char* getOpenCLRegKeyName(void);