summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/lib/osdlib_win32.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/modules/lib/osdlib_win32.cpp')
-rw-r--r--src/osd/modules/lib/osdlib_win32.cpp239
1 files changed, 178 insertions, 61 deletions
diff --git a/src/osd/modules/lib/osdlib_win32.cpp b/src/osd/modules/lib/osdlib_win32.cpp
index 911f95c3bfe..cf3fd7c9320 100644
--- a/src/osd/modules/lib/osdlib_win32.cpp
+++ b/src/osd/modules/lib/osdlib_win32.cpp
@@ -8,27 +8,27 @@
//
//============================================================
-#include <windows.h>
-#include <mmsystem.h>
-
-#include <stdlib.h>
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
-
-#include <cstdio>
-#include <memory>
-
// MAME headers
#include "osdlib.h"
#include "osdcomm.h"
#include "osdcore.h"
#include "strconv.h"
-#ifdef OSD_WINDOWS
#include "winutf8.h"
+#include "winutil.h"
+
+#include <algorithm>
+#include <cstdio>
+#include <cstdlib>
+
+#include <windows.h>
+#include <memoryapi.h>
+
+#ifndef _MSC_VER
+#include <unistd.h>
#endif
+
//============================================================
// GLOBAL VARIABLES
//============================================================
@@ -82,30 +82,6 @@ void osd_process_kill()
TerminateProcess(GetCurrentProcess(), -1);
}
-//============================================================
-// osd_alloc_executable
-//
-// allocates "size" bytes of executable memory. this must take
-// things like NX support into account.
-//============================================================
-
-void *osd_alloc_executable(size_t size)
-{
- return VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
-}
-
-
-//============================================================
-// osd_free_executable
-//
-// frees memory allocated with osd_alloc_executable
-//============================================================
-
-void osd_free_executable(void *ptr, size_t size)
-{
- VirtualFree(ptr, 0, MEM_RELEASE);
-}
-
//============================================================
// osd_break_into_debugger
@@ -130,6 +106,42 @@ void osd_break_into_debugger(const char *message)
#endif
}
+
+//============================================================
+// osd_get_cache_line_size
+//============================================================
+
+std::pair<std::error_condition, unsigned> osd_get_cache_line_size() noexcept
+{
+ DWORD resultsize = 0;
+ if (GetLogicalProcessorInformation(nullptr, &resultsize) || (ERROR_INSUFFICIENT_BUFFER != GetLastError()) || !resultsize)
+ return std::make_pair(std::errc::operation_not_permitted, 0U);
+
+ auto const result = reinterpret_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION *>(std::malloc(resultsize));
+ if (!result)
+ return std::make_pair(std::errc::not_enough_memory, 0U);
+
+ if (!GetLogicalProcessorInformation(result, &resultsize))
+ {
+ std::free(result);
+ return std::make_pair(std::errc::operation_not_permitted, 0U);
+ }
+
+ for (unsigned i = 0; i < (resultsize / sizeof(result[0])); ++i)
+ {
+ if ((RelationCache == result[i].Relationship) && (1 == result[i].Cache.Level))
+ {
+ unsigned const linesize = result[i].Cache.LineSize;
+ std::free(result);
+ return std::make_pair(std::error_condition(), linesize);
+ }
+ }
+
+ std::free(result);
+ return std::make_pair(std::errc::operation_not_permitted, 0U);
+}
+
+
//============================================================
// get_clipboard_text_by_format
//============================================================
@@ -192,25 +204,92 @@ static std::string convert_ansi(LPCVOID data)
// osd_get_clipboard_text
//============================================================
-std::string osd_get_clipboard_text(void)
+std::string osd_get_clipboard_text() noexcept
{
std::string result;
- // try to access unicode text
- if (!get_clipboard_text_by_format(result, CF_UNICODETEXT, convert_wide))
+ // TODO: better error handling
+ try
+ {
+ // try to access unicode text
+ if (!get_clipboard_text_by_format(result, CF_UNICODETEXT, convert_wide))
+ {
+ // try to access ANSI text
+ get_clipboard_text_by_format(result, CF_TEXT, convert_ansi);
+ }
+ }
+ catch (...)
{
- // try to access ANSI text
- get_clipboard_text_by_format(result, CF_TEXT, convert_ansi);
}
return result;
}
//============================================================
+// osd_set_clipboard_text
+//============================================================
+
+std::error_condition osd_set_clipboard_text(std::string_view text) noexcept
+{
+ try
+ {
+ // convert the text to a wide char string and create a moveable global block
+ std::wstring const wtext = osd::text::to_wstring(text);
+ HGLOBAL const clip = GlobalAlloc(GMEM_MOVEABLE, (text.length() + 1) * sizeof(wchar_t));
+ if (!clip)
+ return win_error_to_error_condition(GetLastError());
+ LPWSTR const lock = reinterpret_cast<LPWSTR>(GlobalLock(clip));
+ if (!lock)
+ {
+ DWORD const err(GetLastError());
+ GlobalFree(clip);
+ return win_error_to_error_condition(err);
+ }
+
+ // clear current clipboard contents
+ if (!OpenClipboard(nullptr))
+ {
+ DWORD const err(GetLastError());
+ GlobalUnlock(clip);
+ GlobalFree(clip);
+ return win_error_to_error_condition(err);
+ }
+ if (!EmptyClipboard())
+ {
+ DWORD const err(GetLastError());
+ CloseClipboard();
+ GlobalUnlock(clip);
+ GlobalFree(clip);
+ return win_error_to_error_condition(err);
+ }
+
+ // copy the text (plus NUL terminator) to the moveable block and put it on the clipboard
+ std::copy_n(wtext.c_str(), wtext.length() + 1, lock);
+ GlobalUnlock(clip);
+ if (!SetClipboardData(CF_UNICODETEXT, clip))
+ {
+ DWORD const err(GetLastError());
+ CloseClipboard();
+ GlobalFree(clip);
+ return win_error_to_error_condition(err);
+ }
+
+ // clean up
+ if (!CloseClipboard())
+ return win_error_to_error_condition(GetLastError());
+ return std::error_condition();
+ }
+ catch (std::bad_alloc const &)
+ {
+ return std::errc::not_enough_memory;
+ }
+}
+
+//============================================================
// osd_getpid
//============================================================
-int osd_getpid(void)
+int osd_getpid() noexcept
{
return GetCurrentProcessId();
}
@@ -219,29 +298,25 @@ int osd_getpid(void)
// osd_dynamic_bind
//============================================================
-#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
// for classic desktop applications
#define load_library(filename) LoadLibrary(filename)
-#else
-// for Windows Store universal applications
-#define load_library(filename) LoadPackagedLibrary(filename, 0)
-#endif
namespace osd {
+
+namespace {
+
class dynamic_module_win32_impl : public dynamic_module
{
public:
- dynamic_module_win32_impl(std::vector<std::string> &libraries)
- : m_module(nullptr)
+ dynamic_module_win32_impl(std::vector<std::string> &&libraries) : m_libraries(std::move(libraries))
{
- m_libraries = libraries;
}
virtual ~dynamic_module_win32_impl() override
{
- if (m_module != nullptr)
+ if (m_module)
FreeLibrary(m_module);
- };
+ }
protected:
virtual generic_fptr_t get_symbol_address(char const *symbol) override
@@ -251,20 +326,18 @@ protected:
* one of them, all additional symbols will be loaded from the same library
*/
if (m_module)
- {
return reinterpret_cast<generic_fptr_t>(GetProcAddress(m_module, symbol));
- }
for (auto const &library : m_libraries)
{
- osd::text::tstring tempstr = osd::text::to_tstring(library);
- HMODULE module = load_library(tempstr.c_str());
+ osd::text::tstring const tempstr = osd::text::to_tstring(library);
+ HMODULE const module = load_library(tempstr.c_str());
- if (module != nullptr)
+ if (module)
{
- generic_fptr_t function = reinterpret_cast<generic_fptr_t>(GetProcAddress(module, symbol));
+ auto const function = reinterpret_cast<generic_fptr_t>(GetProcAddress(module, symbol));
- if (function != nullptr)
+ if (function)
{
m_module = module;
return function;
@@ -281,12 +354,56 @@ protected:
private:
std::vector<std::string> m_libraries;
- HMODULE m_module;
+ HMODULE m_module = nullptr;
};
+} // anonymous namespace
+
+
+bool invalidate_instruction_cache(void const *start, std::size_t size) noexcept
+{
+ return FlushInstructionCache(GetCurrentProcess(), start, size) != 0;
+}
+
+
+void *virtual_memory_allocation::do_alloc(std::initializer_list<std::size_t> blocks, unsigned intent, std::size_t &size, std::size_t &page_size) noexcept
+{
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+ SIZE_T s(0);
+ for (std::size_t b : blocks)
+ s += (b + info.dwPageSize - 1) / info.dwPageSize;
+ s *= info.dwPageSize;
+ if (!s)
+ return nullptr;
+ LPVOID const result(VirtualAlloc(nullptr, s, MEM_COMMIT, PAGE_NOACCESS));
+ if (result)
+ {
+ size = s;
+ page_size = info.dwPageSize;
+ }
+ return result;
+}
+
+void virtual_memory_allocation::do_free(void *start, std::size_t size) noexcept
+{
+ VirtualFree(start, 0, MEM_RELEASE);
+}
+
+bool virtual_memory_allocation::do_set_access(void *start, std::size_t size, unsigned access) noexcept
+{
+ DWORD p;
+ if (access & EXECUTE)
+ p = (access & WRITE) ? PAGE_EXECUTE_READWRITE : (access & READ) ? PAGE_EXECUTE_READ : PAGE_EXECUTE;
+ else
+ p = (access & WRITE) ? PAGE_READWRITE : (access & READ) ? PAGE_READONLY : PAGE_NOACCESS;
+ return VirtualAlloc(start, size, MEM_COMMIT, p) != nullptr;
+}
+
+
dynamic_module::ptr dynamic_module::open(std::vector<std::string> &&names)
{
- return std::make_unique<dynamic_module_win32_impl>(names);
+ return std::make_unique<dynamic_module_win32_impl>(std::move(names));
}
} // namespace osd