fs::path HOSTFXR_UTILITY::GetAbsolutePathToHostFxr( const fs::path & dotnetPath ) { std::vector<std::wstring> versionFolders; const auto hostFxrBase = dotnetPath.parent_path() / "host" / "fxr"; LOG_INFOF(L"Resolving absolute path to hostfxr.dll from '%ls'", dotnetPath.c_str()); if (!is_directory(hostFxrBase)) { throw InvalidOperationException(format(L"Unable to find hostfxr directory at %s", hostFxrBase.c_str())); } FindDotNetFolders(hostFxrBase, versionFolders); if (versionFolders.empty()) { throw InvalidOperationException(format(L"Hostfxr directory '%s' doesn't contain any version subdirectories", hostFxrBase.c_str())); } const auto highestVersion = FindHighestDotNetVersion(versionFolders); const auto hostFxrPath = hostFxrBase / highestVersion / "hostfxr.dll"; if (!is_regular_file(hostFxrPath)) { throw InvalidOperationException(format(L"hostfxr.dll not found at '%s'", hostFxrPath.c_str())); } LOG_INFOF(L"hostfxr.dll located at '%ls'", hostFxrPath.c_str()); return hostFxrPath; }
std::shared_ptr<VSRG::Song> LoadSong7KFromFilename(const std::filesystem::path& filename, VSRG::Song *Sng) { if (!filename.has_extension()) { return nullptr; } bool AllocSong = false; if (!Sng) { AllocSong = true; Sng = new VSRG::Song(); } Sng->SongDirectory = filename.parent_path(); for (int i = 0; i < sizeof(LoadersVSRG) / sizeof(loaderVSRGEntry_t); i++) { if (filename.extension() == LoadersVSRG[i].Ext) { Log::LogPrintf("Load %s from disk...", filename.string().c_str()); try { LoadersVSRG[i].LoadFunc(filename, Sng); Log::LogPrintf(" ok\n"); } catch (std::exception &e) { Log::LogPrintf("Failure loading %s: %s\n", filename.string().c_str(), e.what()); } break; } } if (AllocSong) return std::shared_ptr<VSRG::Song>(Sng); return nullptr; }
std::shared_ptr<FileWatch> FileMonitorWin::Watch(const std::filesystem::path& path, const t_callbackFunc& callback, FileWatch::State states) { try { if(!std::filesystem::exists(path)) return nullptr; } catch (...) { return nullptr; } std::filesystem::path directory = (std::filesystem::is_directory(path) || !path.has_parent_path()) ? path : path.parent_path(); // Ugh. std::wstring wpath; #if _MSC_VER >= 1900 wpath = directory.wstring(); #else auto str = directory.string(); wpath.assign(str.begin(), str.end()); #endif // Open the handle to the directory we were asked to watch with the // correct permissions so that we can actually conduct asynchronous // read operations. HANDLE hFile = CreateFileW( wpath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_FLAG_BACKUP_SEMANTICS, nullptr ); if (hFile == INVALID_HANDLE_VALUE) // No such file, what else can we do? return nullptr; // Compose the notification filter based on the user's request DWORD dwNotifyFilter = 0; if(states & FileWatch::State::RENAMED || states & FileWatch::State::DELETED) dwNotifyFilter |= FILE_NOTIFY_CHANGE_FILE_NAME; if(states & FileWatch::State::MODIFIED) dwNotifyFilter |= FILE_NOTIFY_CHANGE_LAST_WRITE; // Need a second-order shared pointer so we can preserve references Entry* pEntry; auto key = m_nextKey++; { std::lock_guard<std::mutex> lk(GetLock()); pEntry = &m_outstanding[key]; pEntry->key = key; } // Need an overlapped structure to track this operation. We'll also be using this to decide // how to notify the true caller. auto watcher = std::shared_ptr<FileWatchWin>( new FileWatchWin(path, callback, dwNotifyFilter, hFile), [this, key](FileWatchWin* fileWatch) { --m_numWatchers; delete fileWatch; m_outstanding.erase(key); } ); pEntry->watcherWeak = watcher; // Attach to the completion port with the FileWatchWin we just constructed if (!CreateIoCompletionPort(hFile, m_hCompletion, key, 0)) { // Something went wrong, can't attach a watcher at this point m_outstanding.erase(key); return nullptr; } // Initial pend, and then return to the controller watcher->ReadDirectoryChanges(); ++m_numWatchers; return watcher; }