remove WDK dependency for OpenCL ICD loader (#102)

* remove dependency on Windows WDK for Windows ICD Loader builds

After this change, instead of including a WDK header file, a
private header file is used with just the definitions needed
for the ICD loader.  The header file is copied unchanged from
the Vulkan loader repo.

* update README to remove WDK dependency

* updated file version to v2.2.8
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7e0b225..9e2d7df 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,6 +50,7 @@
 
 if (WIN32)
     list (APPEND OPENCL_ICD_LOADER_SOURCES 
+        loader/windows/adapter.h
         loader/windows/icd_windows.c
         loader/windows/icd_windows.h
         loader/windows/icd_windows_dxgk.c
@@ -82,28 +83,6 @@
 if (WIN32)
     target_link_libraries (OpenCL cfgmgr32.lib RuntimeObject.lib)
 
-    option (OPENCL_ICD_LOADER_REQUIRE_WDK "Build with D3DKMT support, which requires the Windows WDK." ON)
-    if (OPENCL_ICD_LOADER_REQUIRE_WDK)
-        if(DEFINED ENV{WDKContentRoot})
-            file(GLOB D3DKMT_HEADER "$ENV{WDKContentRoot}/Include/*/km/d3dkmthk.h")
-        else()
-            file(GLOB D3DKMT_HEADER "$ENV{HOMEDRIVE}/Program Files */Windows Kits/10/Include/*/km/d3dkmthk.h")
-        endif()
-
-        if(D3DKMT_HEADER)
-            list(GET D3DKMT_HEADER -1 LATEST_D3DKMT_HEADER)
-            get_filename_component(WDK_DIRECTORY ${LATEST_D3DKMT_HEADER} DIRECTORY)
-            get_filename_component(WDK_DIRECTORY ${WDK_DIRECTORY} DIRECTORY)
-            message(STATUS "Found the Windows WDK in: ${WDK_DIRECTORY}")
-            target_compile_definitions(OpenCL PRIVATE OPENCL_ICD_LOADER_REQUIRE_WDK)
-            target_include_directories(OpenCL PRIVATE ${WDK_DIRECTORY}/um)
-            target_include_directories(OpenCL PRIVATE ${WDK_DIRECTORY}/km)
-            target_include_directories(OpenCL PRIVATE ${WDK_DIRECTORY}/shared)
-        else()
-            message(FATAL_ERROR "The Windows WDK was not found. Consider disabling OPENCL_ICD_LOADER_REQUIRE_WDK. Aborting.")
-        endif()
-    endif()
-
     if(NOT USE_DYNAMIC_VCXX_RUNTIME)
         string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
         string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
diff --git a/README.md b/README.md
index 099f3a6..fcea27c 100644
--- a/README.md
+++ b/README.md
@@ -30,15 +30,6 @@
 To use system OpenCL Headers, please specify the OpenCL Header location using the CMake variable `OPENCL_ICD_LOADER_HEADERS_DIR`.
 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.
-
 The OpenCL ICD Loader uses CMake for its build system.
 If CMake is not provided by your build system or OS package manager, please consult the [CMake website](https://cmake.org).
 
diff --git a/loader/windows/OpenCL.rc b/loader/windows/OpenCL.rc
index 38f2c84..2d983f7 100644
--- a/loader/windows/OpenCL.rc
+++ b/loader/windows/OpenCL.rc
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019 The Khronos Group Inc.
+ * Copyright (c) 2016-2020 The Khronos Group Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
 
 #define OPENCL_ICD_LOADER_VERSION_MAJOR 2
 #define OPENCL_ICD_LOADER_VERSION_MINOR 2
-#define OPENCL_ICD_LOADER_VERSION_REV   7
+#define OPENCL_ICD_LOADER_VERSION_REV   8
 
 #ifdef RC_INVOKED
 
@@ -43,7 +43,7 @@
         BEGIN
             VALUE "FileDescription" ,"OpenCL Client DLL"
             VALUE "ProductName"     ,"Khronos OpenCL ICD Loader"
-            VALUE "LegalCopyright"  ,"Copyright \251 The Khronos Group Inc 2016-2019"
+            VALUE "LegalCopyright"  ,"Copyright \251 The Khronos Group Inc 2016-2020"
             VALUE "FileVersion"     ,OPENCL_ICD_LOADER_VERSION_STRING ".0"
             VALUE "CompanyName"     ,"Khronos Group"
             VALUE "InternalName"    ,"OpenCL"
diff --git a/loader/windows/adapter.h b/loader/windows/adapter.h
new file mode 100644
index 0000000..ef97d66
--- /dev/null
+++ b/loader/windows/adapter.h
@@ -0,0 +1,80 @@
+/*
+* Copyright (c) 2019 The Khronos Group Inc.
+* Copyright (c) 2019 Valve Corporation
+* Copyright (c) 2019 LunarG, Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+* Author: Lenny Komow <lenny@lunarg.com>
+*/
+
+typedef struct LoaderEnumAdapters2 {
+    ULONG adapter_count;
+    struct {
+        UINT handle;
+        LUID luid;
+        ULONG source_count;
+        BOOL present_move_regions_preferred;
+    } * adapters;
+} LoaderEnumAdapters2;
+
+typedef _Check_return_ NTSTATUS(APIENTRY *PFN_LoaderEnumAdapters2)(const LoaderEnumAdapters2 *);
+
+typedef enum AdapterInfoType {
+    LOADER_QUERY_TYPE_REGISTRY = 48,
+} AdapterInfoType;
+
+typedef struct LoaderQueryAdapterInfo {
+    UINT handle;
+    AdapterInfoType type;
+    VOID *private_data;
+    UINT private_data_size;
+} LoaderQueryAdapterInfo;
+
+typedef _Check_return_ NTSTATUS(APIENTRY *PFN_LoaderQueryAdapterInfo)(const LoaderQueryAdapterInfo *);
+
+typedef enum LoaderQueryRegistryType {
+    LOADER_QUERY_REGISTRY_ADAPTER_KEY = 1,
+} LoaderQueryRegistryType;
+
+typedef enum LoaderQueryRegistryStatus {
+    LOADER_QUERY_REGISTRY_STATUS_SUCCESS = 0,
+    LOADER_QUERY_REGISTRY_STATUS_BUFFER_OVERFLOW = 1,
+} LoaderQueryRegistryStatus;
+
+typedef struct LoaderQueryRegistryFlags {
+    union {
+        struct {
+            UINT translate_path : 1;
+            UINT mutable_value : 1;
+            UINT reserved : 30;
+        };
+        UINT value;
+    };
+} LoaderQueryRegistryFlags;
+
+typedef struct LoaderQueryRegistryInfo {
+    LoaderQueryRegistryType query_type;
+    LoaderQueryRegistryFlags query_flags;
+    WCHAR value_name[MAX_PATH];
+    ULONG value_type;
+    ULONG physical_adapter_index;
+    ULONG output_value_size;
+    LoaderQueryRegistryStatus status;
+    union {
+        DWORD output_dword;
+        UINT64 output_qword;
+        WCHAR output_string[1];
+        BYTE output_binary[1];
+    };
+} LoaderQueryRegistryInfo;
diff --git a/loader/windows/icd_windows_dxgk.c b/loader/windows/icd_windows_dxgk.c
index d16986b..6f1568e 100644
--- a/loader/windows/icd_windows_dxgk.c
+++ b/loader/windows/icd_windows_dxgk.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 The Khronos Group Inc.
+ * Copyright (c) 2017-2020 The Khronos Group Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,109 +19,109 @@
 #include "icd.h"
 #include "icd_windows_dxgk.h"
 
-#if defined(OPENCL_ICD_LOADER_REQUIRE_WDK)
 #include <windows.h>
+#include "adapter.h"
 
 #ifndef NTSTATUS
 typedef LONG NTSTATUS;
 #define STATUS_SUCCESS  ((NTSTATUS)0x00000000L)
 #define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023)
-#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
-#endif
-
-#include <d3dkmthk.h>
+#define NT_SUCCESS(status) (((NTSTATUS)(status)) >= 0)
 #endif
 
 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
+    if(GetProcAddress(h, "D3DKMTSubmitPresentBltToHwQueue")) // OS Version check
     {
-        D3DKMT_ADAPTERINFO* pAdapterInfo = NULL;
-        D3DKMT_ENUMADAPTERS2 EnumAdapters;
-        NTSTATUS Status = STATUS_SUCCESS;
+        LoaderEnumAdapters2 EnumAdapters;
+        NTSTATUS status = STATUS_SUCCESS;
 
         char cszLibraryName[MAX_PATH] = { 0 };
-        EnumAdapters.NumAdapters = 0;
-        EnumAdapters.pAdapters = NULL;
-        PFND3DKMT_ENUMADAPTERS2 pEnumAdapters2 = (PFND3DKMT_ENUMADAPTERS2)GetProcAddress((HMODULE)h, "D3DKMTEnumAdapters2");
+        EnumAdapters.adapter_count = 0;
+        EnumAdapters.adapters = NULL;
+        PFN_LoaderEnumAdapters2 pEnumAdapters2 = (PFN_LoaderEnumAdapters2)GetProcAddress(h, "D3DKMTEnumAdapters2");
         if (!pEnumAdapters2)
         {
-            KHR_ICD_TRACE("GetProcAddress failed for D3DKMT_ENUMADAPTERS2\n");
+            KHR_ICD_TRACE("GetProcAddress failed for D3DKMTEnumAdapters2\n");
+            goto out;
+        }
+        PFN_LoaderQueryAdapterInfo pQueryAdapterInfo = (PFN_LoaderQueryAdapterInfo)GetProcAddress(h, "D3DKMTQueryAdapterInfo");
+        if (!pQueryAdapterInfo)
+        {
+            KHR_ICD_TRACE("GetProcAddress failed for D3DKMTQueryAdapterInfo\n");
             goto out;
         }
         while (1)
         {
-            EnumAdapters.NumAdapters = 0;
-            EnumAdapters.pAdapters = NULL;
-            Status = pEnumAdapters2(&EnumAdapters);
-            if (Status == STATUS_BUFFER_TOO_SMALL)
+            EnumAdapters.adapter_count = 0;
+            EnumAdapters.adapters = NULL;
+            status = pEnumAdapters2(&EnumAdapters);
+            if (status == STATUS_BUFFER_TOO_SMALL)
             {
                 // Number of Adapters increased between calls, retry;
                 continue;
             }
-            else if (!NT_SUCCESS(Status))
+            else if (!NT_SUCCESS(status))
             {
-                KHR_ICD_TRACE("D3DKMT_ENUMADAPTERS2 status != SUCCESS\n");
+                KHR_ICD_TRACE("D3DKMTEnumAdapters2 status != SUCCESS\n");
                 goto out;
             }
             break;
         }
-        pAdapterInfo = (D3DKMT_ADAPTERINFO*)malloc(sizeof(D3DKMT_ADAPTERINFO)*(EnumAdapters.NumAdapters));
-        if (pAdapterInfo == NULL)
+        EnumAdapters.adapters = malloc(sizeof(*EnumAdapters.adapters)*(EnumAdapters.adapter_count));
+        if (EnumAdapters.adapters == NULL)
         {
-            KHR_ICD_TRACE("Allocation failure for AdapterInfo buffer\n");
+            KHR_ICD_TRACE("Allocation failure for adapters buffer\n");
             goto out;
         }
-        EnumAdapters.pAdapters = pAdapterInfo;
-        Status = pEnumAdapters2(&EnumAdapters);
-        if (!NT_SUCCESS(Status))
+        status = pEnumAdapters2(&EnumAdapters);
+        if (!NT_SUCCESS(status))
         {
-            KHR_ICD_TRACE("D3DKMT_ENUMADAPTERS2 status != SUCCESS\n");
+            KHR_ICD_TRACE("D3DKMTEnumAdapters2 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++)
+        for (UINT AdapterIndex = 0; AdapterIndex < EnumAdapters.adapter_count; AdapterIndex++)
         {
-            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;
+            LoaderQueryRegistryInfo queryArgs = {0};
+            LoaderQueryRegistryInfo* pQueryArgs = &queryArgs;
+            LoaderQueryRegistryInfo* pQueryBuffer = NULL;
+            queryArgs.query_type = LOADER_QUERY_REGISTRY_ADAPTER_KEY;
+            queryArgs.query_flags.translate_path = TRUE;
+            queryArgs.value_type = REG_SZ;
             result = MultiByteToWideChar(
                 CP_ACP,
                 0,
                 cszOpenCLRegKeyName,
                 szOpenCLRegKeyName,
-                queryArgs.ValueName,
-                ARRAYSIZE(queryArgs.ValueName));
+                queryArgs.value_name,
+                ARRAYSIZE(queryArgs.value_name));
             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))
+            LoaderQueryAdapterInfo queryAdapterInfo = {0};
+            queryAdapterInfo.handle = EnumAdapters.adapters[AdapterIndex].handle;
+            queryAdapterInfo.type = LOADER_QUERY_TYPE_REGISTRY;
+            queryAdapterInfo.private_data = &queryArgs;
+            queryAdapterInfo.private_data_size = sizeof(queryArgs);
+            status = pQueryAdapterInfo(&queryAdapterInfo);
+            if (!NT_SUCCESS(status))
             {
                 // Try a different value type.  Some vendors write the key as a multi-string type.
-                queryArgs.ValueType = REG_MULTI_SZ;
-                Status = D3DKMTQueryAdapterInfo(&queryAdapterInfo);
-                if (NT_SUCCESS(Status))
+                queryArgs.value_type = REG_MULTI_SZ;
+                status = pQueryAdapterInfo(&queryAdapterInfo);
+                if (NT_SUCCESS(status))
                 {
                     KHR_ICD_TRACE("Accepting multi-string registry key type\n");
                 }
@@ -132,29 +132,30 @@
                     continue;
                 }
             }
-            if (NT_SUCCESS(Status) && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_BUFFER_OVERFLOW)
+            if (NT_SUCCESS(status) && pQueryArgs->status == LOADER_QUERY_REGISTRY_STATUS_BUFFER_OVERFLOW)
             {
-                ULONG queryBufferSize = sizeof(D3DDDI_QUERYREGISTRY_INFO) + queryArgs.OutputValueSize;
-                pQueryBuffer = (D3DDDI_QUERYREGISTRY_INFO*)malloc(queryBufferSize);
+                ULONG queryBufferSize = sizeof(LoaderQueryRegistryInfo) + queryArgs.output_value_size;
+                pQueryBuffer = malloc(queryBufferSize);
                 if (pQueryBuffer == NULL)
                     continue;
-                memcpy(pQueryBuffer, &queryArgs, sizeof(D3DDDI_QUERYREGISTRY_INFO));
-                queryAdapterInfo.pPrivateDriverData = pQueryBuffer;
-                queryAdapterInfo.PrivateDriverDataSize = queryBufferSize;
-                Status = D3DKMTQueryAdapterInfo(&queryAdapterInfo);
+                memcpy(pQueryBuffer, &queryArgs, sizeof(LoaderQueryRegistryInfo));
+                queryAdapterInfo.private_data = pQueryBuffer;
+                queryAdapterInfo.private_data_size = queryBufferSize;
+                status = pQueryAdapterInfo(&queryAdapterInfo);
                 pQueryArgs = pQueryBuffer;
             }
-            if (NT_SUCCESS(Status) && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_SUCCESS)
+            if (NT_SUCCESS(status) && pQueryArgs->status == LOADER_QUERY_REGISTRY_STATUS_SUCCESS)
             {
-                wchar_t* pWchar = pQueryArgs->OutputString;
+                wchar_t* pWchar = pQueryArgs->output_string;
                 memset(cszLibraryName, 0, sizeof(cszLibraryName));
                 {
-                    size_t len = wcstombs(cszLibraryName, pWchar, sizeof(cszLibraryName));
+                    size_t len;
+                    wcstombs_s(&len, cszLibraryName, sizeof(cszLibraryName), pWchar, sizeof(cszLibraryName));
                     KHR_ICD_ASSERT(len == (sizeof(cszLibraryName) - 1));
-                    ret |= adapterAdd(cszLibraryName, pAdapterInfo[AdapterIndex].AdapterLuid);
+                    ret |= adapterAdd(cszLibraryName, EnumAdapters.adapters[AdapterIndex].luid);
                 }
             }
-            else if (Status == STATUS_INVALID_PARAMETER && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_FAIL)
+            else if (status == STATUS_INVALID_PARAMETER)
             {
                 free(pQueryBuffer);
                 goto out;
@@ -162,12 +163,10 @@
             free(pQueryBuffer);
         }
 out:
-      free(pAdapterInfo);
+      free(EnumAdapters.adapters);
     }
 
     FreeLibrary(h);
 
-#endif
-#endif
     return ret;
 }