/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuOpen.Win32.cpp Date: 2021-6-12 Author: Reece ***/ #include #include "AuProcesses.hpp" #include "AuOpen.Win32.hpp" #include #include #include #include "Objbase.h" #include "shellapi.h" namespace Aurora::Processes { static AuList gOpenItems; static AuThreadPrimitives::ConditionMutexUnique_t gCondMutex; static AuThreadPrimitives::ConditionVariableUnique_t gCondVariable; static AuThreads::ThreadUnique_t gOpenerThread; static void RunTasks() { AU_LOCK_GUARD(gCondMutex); while (AuIsThreadRunning()) { try { for (const auto &open : gOpenItems) { if (open.empty()) continue; // [*1] ShellExecuteW(nullptr, AuIOFS::DirExists(open) ? L"explore" : L"open", Locale::ConvertFromUTF8(open).c_str(), nullptr, nullptr, SW_SHOWNORMAL); } gOpenItems.clear(); gCondVariable->WaitForSignal(); } catch (...) { Debug::PrintError(); AuLogWarn("An error occurred while dispatching a ShellExecute runner frame"); } } } static void OpenerThread() { CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); RunTasks(); CoUninitialize(); } void InitWin32Opener() { gCondMutex = AuThreadPrimitives::ConditionMutexUnique(); SysAssert(gCondMutex); gCondVariable = AuThreadPrimitives::ConditionVariableUnique(AuUnsafeRaiiToShared(gCondMutex)); SysAssert(gCondVariable); gOpenerThread = AuThreads::ThreadUnique(AuThreads::ThreadInfo( AuMakeShared(AuThreads::IThreadVectorsFunctional::OnEntry_t(std::bind(OpenerThread)), AuThreads::IThreadVectorsFunctional::OnExit_t{}), "COM ShellExecute Runner" )); SysAssert(gOpenerThread); gOpenerThread->Run(); } void DeinitWin32Opener() { gOpenerThread->SendExitSignal(); gCondVariable->Broadcast(); gOpenerThread.reset(); gCondVariable.reset(); gCondMutex.reset(); } AUKN_SYM void OpenUri(const AuString &uri) { AU_LOCK_GUARD(gCondMutex); AuTryInsert(gOpenItems, uri); gCondVariable->Broadcast(); } AUKN_SYM void OpenFile(const AuString &file) { OpenUri(AuIOFS::NormalizePathRet(file)); } }