Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
501}502do {503char base_name[_MAX_FNAME];504char ext[_MAX_EXT];506auto find_data_filename = toUtf8(find_data.cFileName);507if (!_splitpath_s(find_data_filename.c_str(), nullptr, 0, nullptr, 0,508base_name, ARRAYSIZE(base_name), ext, ARRAYSIZE(ext))) {509result->emplace_back(std::string(base_name) + ext);510}511} while (::FindNextFileW(dir_handle, &find_data));512DWORD last_error = ::GetLastError();513::FindClose(dir_handle);514if (last_error != ERROR_NO_MORE_FILES) {515return WindowsError(directory_path, last_error);516}517return Status::OK();518}520Status DeleteFile(const std::string& filename) override {521auto wFilename = toUtf16(filename);522if (!::DeleteFileW(wFilename.c_str())) {523return WindowsError(filename, ::GetLastError());524}525return Status::OK();526}528Status CreateDir(const std::string& dirname) override {529auto wDirname = toUtf16(dirname);530if (!::CreateDirectoryW(wDirname.c_str(), nullptr)) {531return WindowsError(dirname, ::GetLastError());532}533return Status::OK();534}536Status DeleteDir(const std::string& dirname) override {537auto wDirname = toUtf16(dirname);538if (!::RemoveDirectoryW(wDirname.c_str())) {539return WindowsError(dirname, ::GetLastError());540}541return Status::OK();542}544Status GetFileSize(const std::string& filename, uint64_t* size) override {545WIN32_FILE_ATTRIBUTE_DATA file_attributes;546auto wFilename = toUtf16(filename);547if (!::GetFileAttributesExW(wFilename.c_str(), GetFileExInfoStandard,548&file_attributes)) {549return WindowsError(filename, ::GetLastError());550}551ULARGE_INTEGER file_size;552file_size.HighPart = file_attributes.nFileSizeHigh;553file_size.LowPart = file_attributes.nFileSizeLow;554*size = file_size.QuadPart;555return Status::OK();556}558Status RenameFile(const std::string& from, const std::string& to) override {559// Try a simple move first. It will only succeed when |to| doesn't already560// exist.561auto wFrom = toUtf16(from);562auto wTo = toUtf16(to);563if (::MoveFileW(wFrom.c_str(), wTo.c_str())) {564return Status::OK();565}566DWORD move_error = ::GetLastError();568// Try the full-blown replace if the move fails, as ReplaceFile will only569// succeed when |to| does exist. When writing to a network share, we may not570// be able to change the ACLs. Ignore ACL errors then571// (REPLACEFILE_IGNORE_MERGE_ERRORS).572if (::ReplaceFileW(wTo.c_str(), wFrom.c_str(), /*lpBackupFileName=*/nullptr,573REPLACEFILE_IGNORE_MERGE_ERRORS,574/*lpExclude=*/nullptr, /*lpReserved=*/nullptr)) {575return Status::OK();576}577DWORD replace_error = ::GetLastError();578// In the case of FILE_ERROR_NOT_FOUND from ReplaceFile, it is likely that579// |to| does not exist. In this case, the more relevant error comes from the580// call to MoveFile.581if (replace_error == ERROR_FILE_NOT_FOUND ||582replace_error == ERROR_PATH_NOT_FOUND) {583return WindowsError(from, move_error);584} else {585return WindowsError(from, replace_error);586}587}589Status LockFile(const std::string& filename, FileLock** lock) override {590*lock = nullptr;591Status result;592auto wFilename = toUtf16(filename);593ScopedHandle handle = ::CreateFileW(594wFilename.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,595/*lpSecurityAttributes=*/nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,596nullptr);597if (!handle.is_valid()) {598result = WindowsError(filename, ::GetLastError());599} else if (!LockOrUnlock(handle.get(), true)) {600result = WindowsError("lock " + filename, ::GetLastError());601} else {602*lock = new WindowsFileLock(std::move(handle), filename);603}604return result;605}607Status UnlockFile(FileLock* lock) override {608WindowsFileLock* windows_file_lock =609reinterpret_cast<WindowsFileLock*>(lock);610if (!LockOrUnlock(windows_file_lock->handle().get(), false)) {611return WindowsError("unlock " + windows_file_lock->filename(),612::GetLastError());613}614delete windows_file_lock;615return Status::OK();616}618void Schedule(void (*background_work_function)(void* background_work_arg),619void* background_work_arg) override;621void StartThread(void (*thread_main)(void* thread_main_arg),622void* thread_main_arg) override {623std::thread new_thread(thread_main, thread_main_arg);624new_thread.detach();625}627Status GetTestDirectory(std::string* result) override {628const char* env = getenv("TEST_TMPDIR");629if (env && env[0] != '\0') {630*result = env;631return Status::OK();632}634wchar_t wtmp_path[MAX_PATH];635if (!GetTempPathW(ARRAYSIZE(wtmp_path), wtmp_path)) {636return WindowsError("GetTempPath", ::GetLastError());637}638std::string tmp_path = toUtf8(std::wstring(wtmp_path));639std::stringstream ss;640ss << tmp_path << "leveldbtest-" << std::this_thread::get_id();641*result = ss.str();643// Directory may already exist644CreateDir(*result);645return Status::OK();646}648Status NewLogger(const std::string& filename, Logger** result) override {649auto wFilename = toUtf16(filename);650std::FILE* fp = _wfopen(wFilename.c_str(), L"w");651if (fp == nullptr) {652*result = nullptr;653return WindowsError(filename, ::GetLastError());654} else {655*result = new WindowsLogger(fp);656return Status::OK();657}658}660uint64_t NowMicros() override {661// GetSystemTimeAsFileTime typically has a resolution of 10-20 msec.662// TODO(cmumford): Switch to GetSystemTimePreciseAsFileTime which is663// available in Windows 8 and later.664FILETIME ft;665::GetSystemTimeAsFileTime(&ft);666// Each tick represents a 100-nanosecond intervals since January 1, 1601667// (UTC).668uint64_t num_ticks =669(static_cast<uint64_t>(ft.dwHighDateTime) << 32) + ft.dwLowDateTime;670return num_ticks / 10;671}673void SleepForMicroseconds(int micros) override {674std::this_thread::sleep_for(std::chrono::microseconds(micros));675}677private:678[[noreturn]] void BackgroundThreadMain();680[[noreturn]] static void BackgroundThreadEntryPoint(WindowsEnv* env) {681env->BackgroundThreadMain();682}684// Stores the work item data in a Schedule() call.685//686// Instances are constructed on the thread calling Schedule() and used on the687// background thread.688//689// This structure is thread-safe because it is immutable.690struct BackgroundWorkItem {691explicit BackgroundWorkItem(void (*function)(void* arg), void* arg)692: function(function), arg(arg) {}694void (*const function)(void*);695void* const arg;696};698port::Mutex background_work_mutex_;699port::CondVar background_work_cv_ GUARDED_BY(background_work_mutex_);700bool started_background_thread_ GUARDED_BY(background_work_mutex_);702std::queue<BackgroundWorkItem> background_work_queue_703GUARDED_BY(background_work_mutex_);705Limiter mmap_limiter_; // Thread-safe.707// Converts a Windows wide multi-byte UTF-16 string to a UTF-8 string.708// See http://utf8everywhere.org/#windows709std::string toUtf8(const std::wstring& wstr) {710if (wstr.empty()) return std::string();711int size_needed = WideCharToMultiByte(712CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);713std::string strTo(size_needed, 0);714WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0],715size_needed, NULL, NULL);716return strTo;717}719// Converts a UTF-8 string to a Windows UTF-16 multi-byte wide character720// string.721// See http://utf8everywhere.org/#windows722std::wstring toUtf16(const std::string& str) {723if (str.empty()) return std::wstring();724int size_needed =725MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);726std::wstring strTo(size_needed, 0);727MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &strTo[0],728size_needed);729return strTo;730}731};733// Return the maximum number of concurrent mmaps.734int MaxMmaps() { return g_mmap_limit; }736WindowsEnv::WindowsEnv()737: background_work_cv_(&background_work_mutex_),738started_background_thread_(false),739mmap_limiter_(MaxMmaps()) {}741void WindowsEnv::Schedule(742void (*background_work_function)(void* background_work_arg),743void* background_work_arg) {744background_work_mutex_.Lock();746// Start the background thread, if we haven't done so already.747if (!started_background_thread_) {748started_background_thread_ = true;749std::thread background_thread(WindowsEnv::BackgroundThreadEntryPoint, this);750background_thread.detach();
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.