Rewrite CLOn12 loader in C (#179)

* Rewrite CLOn12 loader in C

* Remove additional now-unneeded extern "C" guards for khrEnableTrace

* Fix trace message

Co-authored-by: Ben Ashbaugh <ben.ashbaugh@intel.com>

Co-authored-by: Ben Ashbaugh <ben.ashbaugh@intel.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 06c87bf..c8d5e0e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -69,7 +69,6 @@
     loader/icd_platform.h)
 
 if (WIN32)
-    enable_language (CXX)
     list (APPEND OPENCL_ICD_LOADER_SOURCES
         loader/windows/adapter.h
         loader/windows/icd_windows.c
@@ -79,7 +78,7 @@
         loader/windows/icd_windows_envvars.c
         loader/windows/icd_windows_hkr.c
         loader/windows/icd_windows_hkr.h
-        loader/windows/icd_windows_apppackage.cpp
+        loader/windows/icd_windows_apppackage.c
         loader/windows/icd_windows_apppackage.h
         loader/windows/OpenCL.def
         loader/windows/OpenCL.rc)
diff --git a/loader/icd.h b/loader/icd.h
index dba42aa..0c9861a 100644
--- a/loader/icd.h
+++ b/loader/icd.h
@@ -85,13 +85,7 @@
 // the global state
 extern KHRicdVendor * khrIcdVendors;
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-    extern int khrEnableTrace;
-#ifdef __cplusplus
-}
-#endif
+extern int khrEnableTrace;
 
 #if defined(CL_ENABLE_LAYERS)
 /*
diff --git a/loader/windows/icd_windows_apppackage.c b/loader/windows/icd_windows_apppackage.c
new file mode 100644
index 0000000..da08438
--- /dev/null
+++ b/loader/windows/icd_windows_apppackage.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017-2019 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.
+ * 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.
+ *
+ * OpenCL is a trademark of Apple Inc. used under license by Khronos.
+ */
+
+#include <icd.h>
+#include "icd_windows_apppackage.h"
+
+#ifdef OPENCL_ICD_LOADER_DISABLE_OPENCLON12
+
+bool khrIcdOsVendorsEnumerateAppPackage(void)
+{
+    KHR_ICD_TRACE("OpenCLOn12 is disabled\n");
+    return false;
+}
+
+#else
+
+#include <AppModel.h>
+
+bool khrIcdOsVendorsEnumerateAppPackage(void)
+{
+    UINT32 numPackages = 0, bufferLength = 0;
+    PCWSTR familyName = L"Microsoft.D3DMappingLayers_8wekyb3d8bbwe";
+    if (ERROR_INSUFFICIENT_BUFFER != GetPackagesByPackageFamily(familyName,
+                                                                &numPackages, NULL,
+                                                                &bufferLength, NULL) ||
+        numPackages == 0 || bufferLength == 0)
+    {
+        KHR_ICD_TRACE("Failed to find mapping layers packages by family name\n");
+        return false;
+    }
+
+    bool ret = false;
+    WCHAR *buffer = malloc(sizeof(WCHAR) * bufferLength);
+    PWSTR *packages = malloc(sizeof(PWSTR) * numPackages);
+    if (!buffer || !packages)
+    {
+        KHR_ICD_TRACE("Failed to allocate memory for package names\n");
+        goto cleanup;
+    }
+
+    if (ERROR_SUCCESS != GetPackagesByPackageFamily(familyName,
+                                                    &numPackages, packages,
+                                                    &bufferLength, buffer))
+    {
+        KHR_ICD_TRACE("Failed to get mapping layers package full names\n");
+        goto cleanup;
+    }
+
+    UINT32 pathLength = 0;
+    WCHAR path[MAX_PATH];
+    if (ERROR_INSUFFICIENT_BUFFER != GetPackagePathByFullName(packages[0], &pathLength, NULL) ||
+        pathLength > MAX_PATH ||
+        ERROR_SUCCESS != GetPackagePathByFullName(packages[0], &pathLength, path))
+    {
+        KHR_ICD_TRACE("Failed to get mapping layers package path length\n");
+        goto cleanup;
+    }
+
+#if defined(_M_AMD64)
+#define PLATFORM_PATH L"x64"
+#elif defined(_M_ARM)
+#define PLATFORM_PATH L"arm"
+#elif defined(_M_ARM64)
+#define PLATFORM_PATH L"arm64"
+#elif defined(_M_IX86)
+#define PLATFORM_PATH L"x86"
+#endif
+
+    wchar_t dllPath[MAX_PATH];
+    wcscpy_s(dllPath, MAX_PATH, path);
+    wcscat_s(dllPath, MAX_PATH, L"\\" PLATFORM_PATH L"\\OpenCLOn12.dll");
+
+    char narrowDllPath[MAX_PATH];
+    WideCharToMultiByte(CP_ACP, 0, dllPath, -1, narrowDllPath, MAX_PATH, NULL, NULL);
+
+    ret = adapterAdd(narrowDllPath, ZeroLuid);
+
+cleanup:
+    free(buffer);
+    free(packages);
+    return ret;
+}
+
+#endif
diff --git a/loader/windows/icd_windows_apppackage.cpp b/loader/windows/icd_windows_apppackage.cpp
deleted file mode 100644
index b305c5d..0000000
--- a/loader/windows/icd_windows_apppackage.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2017-2019 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.
- * 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.
- *
- * OpenCL is a trademark of Apple Inc. used under license by Khronos.
- */
-
-#include "icd.h"
-#include "icd_windows.h"
-
-#ifdef OPENCL_ICD_LOADER_DISABLE_OPENCLON12
-
-extern "C" bool khrIcdOsVendorsEnumerateAppPackage()
-{
-    KHR_ICD_TRACE("OpenCLOn12 is disabled\n");
-    return false;
-}
-
-#else
-
-#include "icd_windows_apppackage.h"
-
-#include <windows.management.deployment.h>
-#include <wrl/client.h>
-#include <wrl/wrappers/corewrappers.h>
-
-#include <locale>
-#include <codecvt>
-
-template <typename F>
-struct ScopeExit {
-    ScopeExit(F&& f) : f(std::forward<F>(f)) {}
-    ~ScopeExit() { f(); }
-    F f;
-};
-
-template <typename F>
-inline ScopeExit<F> MakeScopeExit(F&& f) {
-    return ScopeExit<F>(std::forward<F>(f));
-};
-
-using namespace Microsoft::WRL;
-using namespace Microsoft::WRL::Wrappers;
-
-extern "C" bool khrIcdOsVendorsEnumerateAppPackage()
-{
-    HRESULT hrInit = Windows::Foundation::Initialize(RO_INIT_MULTITHREADED);
-    if (hrInit == RPC_E_CHANGED_MODE)
-    {
-        hrInit = Windows::Foundation::Initialize(RO_INIT_SINGLETHREADED);
-    }
-    if (FAILED(hrInit))
-    {
-        KHR_ICD_TRACE("Failed to init WinRT\n");
-        return false;
-    }
-    auto Cleanup = MakeScopeExit([]()
-        {
-            Windows::Foundation::Uninitialize();
-        });
-
-    using ABI::Windows::Management::Deployment::IPackageManager;
-    ComPtr<IPackageManager> packageManager;
-    if (FAILED(Windows::Foundation::ActivateInstance(
-        HStringReference(RuntimeClass_Windows_Management_Deployment_PackageManager).Get(),
-        &packageManager)))
-    {
-        KHR_ICD_TRACE("Failed to get package manager\n");
-        return false;
-    }
-
-    using IPackageCollection = ABI::Windows::Foundation::Collections::__FIIterable_1_Windows__CApplicationModel__CPackage_t;
-    ComPtr<IPackageCollection> collection;
-    if (FAILED(packageManager->FindPackagesByUserSecurityIdPackageFamilyName(
-        HStringReference(L"").Get(),
-        HStringReference(L"Microsoft.D3DMappingLayers_8wekyb3d8bbwe").Get(),
-        &collection)))
-    {
-        KHR_ICD_TRACE("Failed to find mapping layers package\n");
-        return false;
-    }
-
-    using IPackageIterator = ABI::Windows::Foundation::Collections::IIterator<
-        ABI::Windows::ApplicationModel::Package*>;
-    ComPtr<IPackageIterator> iter;
-    if (FAILED(collection->First(&iter)))
-    {
-        KHR_ICD_TRACE("Failed to get package collection iterator\n");
-        return false;
-    }
-
-    while ([&iter]()
-        {
-            boolean hasCurrent = false;
-            return SUCCEEDED(iter->get_HasCurrent(&hasCurrent)) && hasCurrent;
-        }())
-    {
-        using ABI::Windows::ApplicationModel::IPackage;
-        ComPtr<IPackage> package;
-        if (FAILED(iter->get_Current(&package)))
-        {
-            KHR_ICD_TRACE("Failed to get package\n");
-            boolean hasCurrent = false;
-            (void)iter->MoveNext(&hasCurrent);
-            continue;
-        }
-
-        boolean hasCurrent = false;
-        (void)iter->MoveNext(&hasCurrent);
-
-        using ABI::Windows::Storage::IStorageFolder;
-        ComPtr<IStorageFolder> folder;
-        if (FAILED(package->get_InstalledLocation(&folder)))
-        {
-            KHR_ICD_TRACE("Failed to get package install folder\n");
-            continue;
-        }
-
-        using ABI::Windows::Storage::IStorageItem;
-        ComPtr<IStorageItem> item;
-        if (FAILED(folder.As(&item)))
-        {
-            KHR_ICD_TRACE("Failed to convert folder to storage item\n");
-            continue;
-        }
-
-        HString path;
-        if (FAILED(item->get_Path(path.GetAddressOf())))
-        {
-            KHR_ICD_TRACE("Failed to get path\n");
-            continue;
-        }
-
-        UINT pathSize = 0;
-        auto rawPath = path.GetRawBuffer(&pathSize);
-        if (pathSize == 0 || rawPath == nullptr)
-        {
-            KHR_ICD_TRACE("Failed to get path\n");
-            continue;
-        }
-        
-#if defined(_M_AMD64)
-#define PLATFORM_PATH L"x64"
-#elif defined(_M_ARM)
-#define PLATFORM_PATH L"arm"
-#elif defined(_M_ARM64)
-#define PLATFORM_PATH L"arm64"
-#elif defined(_M_IX86)
-#define PLATFORM_PATH L"x86"
-#endif
-
-        wchar_t dllPath[MAX_PATH];
-        wcscpy_s(dllPath, rawPath);
-        wcscat_s(dllPath, L"\\" PLATFORM_PATH L"\\OpenCLOn12.dll");
-
-        std::wstring_convert<std::codecvt_utf8<wchar_t>> convert;
-        std::string narrowDllPath = convert.to_bytes(dllPath);
-
-        adapterAdd(narrowDllPath.c_str(), {});
-        return true;
-    }
-    return false;
-}
-
-#endif
diff --git a/loader/windows/icd_windows_apppackage.h b/loader/windows/icd_windows_apppackage.h
index d4c55da..5419ad4 100644
--- a/loader/windows/icd_windows_apppackage.h
+++ b/loader/windows/icd_windows_apppackage.h
@@ -19,7 +19,4 @@
 #include <stdbool.h>
 #include "icd_windows.h"
 
-#ifdef __cplusplus
-extern "C"
-#endif
 bool khrIcdOsVendorsEnumerateAppPackage(void);