diff options
Diffstat (limited to 'libs/usvfs/src/shared/winapi.cpp')
| -rw-r--r-- | libs/usvfs/src/shared/winapi.cpp | 490 |
1 files changed, 0 insertions, 490 deletions
diff --git a/libs/usvfs/src/shared/winapi.cpp b/libs/usvfs/src/shared/winapi.cpp deleted file mode 100644 index e28a13c..0000000 --- a/libs/usvfs/src/shared/winapi.cpp +++ /dev/null @@ -1,490 +0,0 @@ -/* -Userspace Virtual Filesystem - -Copyright (C) 2015 Sebastian Herbord. All rights reserved. - -This file is part of usvfs. - -usvfs is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -usvfs is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with usvfs. If not, see <http://www.gnu.org/licenses/>. -*/ -#include "winapi.h" -#include "exceptionex.h" -#include "logging.h" -#include "ntdll_declarations.h" -#include "stringcast.h" -#include "stringutils.h" -#include "unicodestring.h" - -namespace winapi::ansi -{ - -std::string getModuleFileName(HMODULE module, HANDLE process) -{ - std::wstring result = wide::getModuleFileName(module, process); - return usvfs::shared::string_cast<std::string>(result); -} - -std::string getCurrentDirectory() -{ - std::string result; - DWORD required = GetCurrentDirectoryA(0, nullptr); - if (required == 0UL) { - throw usvfs::shared::windows_error("failed to determine current working directory"); - } - result.resize(required); - GetCurrentDirectoryA(required, &result[0]); - result.resize(required - 1); - return result; -} - -std::pair<std::string, std::string> getFullPathName(LPCSTR fileName) -{ - static const int INIT_SIZE = 128; - std::string result; - result.resize(INIT_SIZE); - LPSTR filePart = nullptr; - DWORD requiredSize = GetFullPathNameA(fileName, INIT_SIZE, &result[0], &filePart); - if (requiredSize >= INIT_SIZE) { - result.resize(requiredSize); - GetFullPathNameA(fileName, requiredSize, &result[0], &filePart); - } - if (requiredSize != 0UL) { - return std::make_pair(result, std::string(filePart != nullptr ? filePart : "")); - } else { - return make_pair(result, std::string()); - } -} - -} // namespace winapi::ansi - -namespace winapi::wide -{ - -std::wstring getModuleFileName(HMODULE module, HANDLE process) -{ - std::wstring result; - result.resize(64); - DWORD rc = 0UL; - - while ((rc = (process == INVALID_HANDLE_VALUE) - ? ::GetModuleFileNameW(module, &result[0], - static_cast<DWORD>(result.size())) - : ::GetModuleFileNameExW(process, module, &result[0], - static_cast<DWORD>(result.size()))) == - result.size()) { - result.resize(result.size() * 2); - } - - if (rc == 0UL) { - if (::GetLastError() == ERROR_PARTIAL_COPY) { -#if BOOST_ARCH_X86_64 - return L"unknown (32-bit process)"; -#else - return L"unknown (64-bit process)"; -#endif - } else { - throw usvfs::shared::windows_error("failed to retrieve module file name"); - } - } - - result.resize(rc); - - return result; -} - -std::pair<std::wstring, std::wstring> getFullPathName(LPCWSTR fileName) -{ - wchar_t buf1[MAX_PATH]; - std::vector<wchar_t> buf2; - wchar_t* result = buf1; - LPWSTR filePart = nullptr; - DWORD requiredSize = GetFullPathNameW(fileName, MAX_PATH, result, &filePart); - if (requiredSize >= MAX_PATH) { - buf2.resize(requiredSize); - result = &buf2[0]; - requiredSize = GetFullPathNameW(fileName, requiredSize, result, &filePart); - } - return make_pair(std::wstring(result, requiredSize), - std::wstring((requiredSize && filePart) ? filePart : L"")); -} - -std::wstring getCurrentDirectory() -{ - // really great api this (::GetCurrentDirectoryW) - // - if it succeeds, returns size in characters WITHOUT zero termination - // - if it fails due to buffer too small, returns size in characters WITH zero - // termination - // - if it fails for other reasons, returns 0 - std::wstring result; - DWORD required = GetCurrentDirectoryW(0, nullptr); - if (required == 0UL) { - throw usvfs::shared::windows_error("failed to determine current working directory"); - } - result.resize(required); - GetCurrentDirectoryW(required, &result[0]); - result.resize(required - 1); - return result; -} - -std::wstring getKnownFolderPath(REFKNOWNFOLDERID folderID) -{ - PWSTR writablePath; - - ::SHGetKnownFolderPath(folderID, 0, nullptr, &writablePath); - - ON_BLOCK_EXIT([writablePath]() { - ::CoTaskMemFree(writablePath); - }); - - return std::wstring(writablePath); -} - -} // namespace winapi::wide - -namespace winapi::ex -{ - -std::pair<uintptr_t, uintptr_t> getSectionRange(HANDLE moduleHandle) -{ - std::pair<uintptr_t, uintptr_t> result; - bool found = false; - uintptr_t exeModule = reinterpret_cast<uintptr_t>(moduleHandle); - if (exeModule == 0) { - throw std::runtime_error("failed to determine address range of executable"); - } - - std::pair<uintptr_t, uintptr_t> totalRange{UINT_MAX, 0}; - - PIMAGE_DOS_HEADER dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(exeModule); - PIMAGE_NT_HEADERS ntHeader = - reinterpret_cast<PIMAGE_NT_HEADERS>(exeModule + dosHeader->e_lfanew); - PIMAGE_SECTION_HEADER sectionHeader = - reinterpret_cast<PIMAGE_SECTION_HEADER>(ntHeader + 1); - for (int i = 0; i < ntHeader->FileHeader.NumberOfSections && !found; ++i) { - if (memcmp(sectionHeader->Name, ".text", 5) == 0) { - result.first = exeModule + sectionHeader->VirtualAddress; - result.second = result.first + sectionHeader->Misc.VirtualSize; - found = true; - } else { - uintptr_t start = exeModule + sectionHeader->VirtualAddress; - totalRange.first = std::min(totalRange.first, start); - totalRange.second = std::max<uintptr_t>(totalRange.second, - start + sectionHeader->Misc.VirtualSize); - } - ++sectionHeader; - } - - if (!found) { - return totalRange; - } - - return result; -} - -OSVersion getOSVersion() -{ - RTL_OSVERSIONINFOEXW versionInfo; - ZeroMemory(&versionInfo, sizeof(RTL_OSVERSIONINFOEXW)); - versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); - RtlGetVersion((PRTL_OSVERSIONINFOW)&versionInfo); - - OSVersion result; - result.major = versionInfo.dwMajorVersion; - result.minor = versionInfo.dwMinorVersion; - result.build = versionInfo.dwBuildNumber; - result.platformid = versionInfo.dwPlatformId; - result.servicpack = - versionInfo.wServicePackMajor << 16 | versionInfo.wServicePackMinor; - return result; -} - -} // namespace winapi::ex - -namespace winapi::ex::ansi -{ - -std::string errorString(DWORD errorCode) -{ - std::ostringstream finalMessage; - - LPSTR buffer = nullptr; - - DWORD currentErrorCode = GetLastError(); - - errorCode = - errorCode != std::numeric_limits<DWORD>::max() ? errorCode : currentErrorCode; - - // TODO: the message is not english? - if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - nullptr, errorCode, - 0 //, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) - , - (LPSTR)&buffer, 0, nullptr) == 0) { - finalMessage << "(unknown error [" << errorCode << "])"; - } else { - if (buffer != nullptr) { - size_t end = strlen(buffer) - 1; - while ((buffer[end] == '\n') || (buffer[end] == '\r')) { - buffer[end--] = '\0'; - } - finalMessage << "(" << buffer << " [" << errorCode << "])"; - LocalFree(buffer); // allocated by FormatMessage - } - } - - SetLastError(currentErrorCode); // restore error code because FormatMessage might - // have modified it - return finalMessage.str(); -} - -std::string toString(const FILETIME& time) -{ - SYSTEMTIME temp; - FileTimeToSystemTime(&time, &temp); - std::ostringstream stream; - stream << temp.wYear << "-" << temp.wMonth << "-" << temp.wDay << temp.wHour << ":" - << temp.wMinute << ":" << temp.wSecond; - return stream.str(); -} - -LPCSTR GetBaseName(LPCSTR string) -{ - LPCSTR result = string + strlen(string) - 1; - while (result > string) { - if ((*result == '\\') || (*result == '/')) { - ++result; - break; - } else { - --result; - } - } - return result; -} - -} // namespace winapi::ex::ansi - -namespace winapi::ex::wide -{ - -bool fileExists(LPCWSTR fileName, bool* isDirectory) -{ - DWORD attrib = GetFileAttributesW(fileName); - - if (attrib == INVALID_FILE_ATTRIBUTES) { - return false; - } else { - if (isDirectory != nullptr) { - *isDirectory = (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; - } - return true; - } -} - -std::wstring errorString(DWORD errorCode) -{ - std::wostringstream finalMessage; - - LPWSTR buffer = nullptr; - - DWORD currentErrorCode = GetLastError(); - - errorCode = - errorCode != std::numeric_limits<DWORD>::max() ? errorCode : currentErrorCode; - - // TODO: the message is not english? - if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - nullptr, errorCode, - 0 //, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) - , - (LPWSTR)&buffer, 0, nullptr) == 0) { - finalMessage << L"(unknown error [" << errorCode << "])"; - } else { - if (buffer != nullptr) { - size_t end = wcslen(buffer) - 1; - while ((buffer[end] == L'\n') || (buffer[end] == L'\r')) { - buffer[end--] = L'\0'; - } - finalMessage << L"(" << buffer << L" [" << errorCode << L"])"; - LocalFree(buffer); // allocated by FormatMessage - } - } - - SetLastError(currentErrorCode); // restore error code because FormatMessage might - // have modified it - return finalMessage.str(); -} - -std::wstring toString(const FILETIME& time) -{ - SYSTEMTIME temp; - FileTimeToSystemTime(&time, &temp); - std::wostringstream stream; - stream << temp.wYear << "-" << temp.wMonth << "-" << temp.wDay << temp.wHour << ":" - << temp.wMinute << ":" << temp.wSecond; - return stream.str(); -} - -LPCWSTR GetBaseName(LPCWSTR string) -{ - LPCWSTR result; - if ((string == nullptr) || (string[0] == L'\0')) { - result = string; - } else { - result = string + wcslen(string) - 1; - } - - while (result > string) { - if ((*result == L'\\') || (*result == L'/')) { - ++result; - break; - } else { - --result; - } - } - return result; -} - -LPWSTR GetBaseName(LPWSTR path) -{ - LPCWSTR result = GetBaseName(static_cast<LPCWSTR>(path)); - return const_cast<LPWSTR>(result); -} - -std::wstring getSectionName(PVOID addressIn, HANDLE process) -{ - if (process == nullptr) { - process = GetCurrentProcess(); - } - HMODULE modules[1024]; - intptr_t address = reinterpret_cast<intptr_t>(addressIn); - DWORD required; - if (::EnumProcessModules(process, modules, sizeof(modules), &required)) { - for (DWORD i = 0; i < (std::min<DWORD>(1024UL, required) / sizeof(HMODULE)); ++i) { - std::pair<intptr_t, intptr_t> range = getSectionRange(modules[i]); - if ((address > range.first) && (address < range.second)) { - try { - return winapi::wide::getModuleFileName(modules[i], process); - } catch (const std::exception&) { - return std::wstring(L"unknown"); - } - } - } - } - return std::wstring(L"unknown"); -} - -std::vector<FileResult> quickFindFiles(LPCWSTR directoryName, LPCWSTR pattern) -{ - std::vector<FileResult> result; - - static const unsigned int BUFFER_SIZE = 1024; - - HANDLE hdl = CreateFileW(directoryName, GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); - - ON_BLOCK_EXIT([hdl]() { - CloseHandle(hdl); - }); - - uint8_t buffer[BUFFER_SIZE]; - - NTSTATUS res = STATUS_SUCCESS; // status success - while (res == STATUS_SUCCESS) { - IO_STATUS_BLOCK status; - - res = NtQueryDirectoryFile( - hdl, nullptr, nullptr, nullptr, &status, buffer, BUFFER_SIZE, - FileFullDirectoryInformation, FALSE, - static_cast<PUNICODE_STRING>(usvfs::UnicodeString(pattern)), FALSE); - if (res == STATUS_SUCCESS) { - FILE_FULL_DIR_INFORMATION* info = - reinterpret_cast<FILE_FULL_DIR_INFORMATION*>(buffer); - void* endPos = buffer + status.Information; - while (info < endPos) { - FileResult file; - file.fileName = - std::wstring(info->FileName, info->FileNameLength / sizeof(wchar_t)); - file.attributes = info->FileAttributes; - - result.push_back(file); - if (info->NextEntryOffset == 0) { - break; - } else { - info = reinterpret_cast<FILE_FULL_DIR_INFORMATION*>( - reinterpret_cast<uint8_t*>(info) + info->NextEntryOffset); - } - } - } - } - - return result; -} - -bool createPath(boost::filesystem::path path, LPSECURITY_ATTRIBUTES securityAttributes) -{ - // sanity and guaranteed recursion end: - if (!path.has_relative_path()) - throw usvfs::shared::windows_error( - "createPath() refusing to create non-existing top level path: " + - path.string()); - - DWORD attr = GetFileAttributesW(path.c_str()); - DWORD err = GetLastError(); - if (attr != INVALID_FILE_ATTRIBUTES) { - if (attr & FILE_ATTRIBUTE_DIRECTORY) - return false; // if directory already exists all is good - else - throw usvfs::shared::windows_error("createPath() called on a file: " + - path.string()); - } - if (err != ERROR_FILE_NOT_FOUND && err != ERROR_PATH_NOT_FOUND) - throw usvfs::shared::windows_error( - "createPath() GetFileAttributesW failed on: " + path.string(), err); - - if (err != ERROR_FILE_NOT_FOUND) // ERROR_FILE_NOT_FOUND means parent directory - // already exists - createPath(path.parent_path(), - securityAttributes); // otherwise create parent directory (recursively) - - BOOL res = CreateDirectoryW(path.c_str(), securityAttributes); - if (!res) { - err = GetLastError(); - throw usvfs::shared::windows_error( - "createPath() CreateDirectoryW failed on: " + path.string(), err); - } - return true; -} - -std::wstring getWindowsBuildLab(bool ex) -{ - HKEY hKey = nullptr; - auto res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)", 0, - KEY_READ, &hKey); - if (res != ERROR_SUCCESS || !hKey) - return L"Opening HKLM Windows NT\\CurrentVersion failed?!"; - WCHAR buf[200]; - DWORD size = static_cast<DWORD>(sizeof(buf)); - res = RegQueryValueExW(hKey, ex ? L"BuildLabEx" : L"BuildLab", NULL, NULL, - reinterpret_cast<LPBYTE>(buf), &size); - if (res != ERROR_SUCCESS || size > sizeof(buf)) - return ex ? L"BuildLabEx reg value not found?!" : L"BuildLab reg value not found?!"; - size /= sizeof(buf[0]); - if (size && !buf[size - 1]) - --size; - return std::wstring(buf, size); -} - -} // namespace winapi::ex::wide |
