1 // license:BSD-3-Clause
2 // copyright-holders:Olivier Galibert, R. Belmont
3 //============================================================
4 //
5 // sdlos_*.c - OS specific low level code
6 //
7 // SDLMAME by Olivier Galibert and R. Belmont
8 //
9 //============================================================
10
11 #include <windows.h>
12 #include <mmsystem.h>
13
14 #include <cstdlib>
15 #ifndef _MSC_VER
16 #include <unistd.h>
17 #endif
18
19 #include <cstdio>
20 #include <memory>
21
22 // MAME headers
23 #include "osdlib.h"
24 #include "osdcomm.h"
25 #include "osdcore.h"
26 #include "strconv.h"
27
28 #ifdef OSD_WINDOWS
29 #include "winutf8.h"
30 #endif
31
32 //============================================================
33 // GLOBAL VARIABLES
34 //============================================================
35
36 #ifdef OSD_WINDOWS
37 void (*s_debugger_stack_crawler)() = nullptr;
38 #endif
39
40
41 //============================================================
42 // osd_getenv
43 //============================================================
44
osd_getenv(const char * name)45 const char *osd_getenv(const char *name)
46 {
47 return getenv(name);
48 }
49
50
51 //============================================================
52 // osd_setenv
53 //============================================================
54
osd_setenv(const char * name,const char * value,int overwrite)55 int osd_setenv(const char *name, const char *value, int overwrite)
56 {
57 char *buf;
58 int result;
59
60 if (!overwrite)
61 {
62 if (osd_getenv(name) != nullptr)
63 return 0;
64 }
65 buf = (char *) malloc(strlen(name)+strlen(value)+2);
66 sprintf(buf, "%s=%s", name, value);
67 result = putenv(buf);
68
69 /* will be referenced by environment
70 * Therefore it is not freed here
71 */
72
73 return result;
74 }
75
76 //============================================================
77 // osd_process_kill
78 //============================================================
79
osd_process_kill()80 void osd_process_kill()
81 {
82 TerminateProcess(GetCurrentProcess(), -1);
83 }
84
85 //============================================================
86 // osd_alloc_executable
87 //
88 // allocates "size" bytes of executable memory. this must take
89 // things like NX support into account.
90 //============================================================
91
osd_alloc_executable(size_t size)92 void *osd_alloc_executable(size_t size)
93 {
94 return VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
95 }
96
97
98 //============================================================
99 // osd_free_executable
100 //
101 // frees memory allocated with osd_alloc_executable
102 //============================================================
103
osd_free_executable(void * ptr,size_t size)104 void osd_free_executable(void *ptr, size_t size)
105 {
106 VirtualFree(ptr, 0, MEM_RELEASE);
107 }
108
109
110 //============================================================
111 // osd_break_into_debugger
112 //============================================================
113
osd_break_into_debugger(const char * message)114 void osd_break_into_debugger(const char *message)
115 {
116 #ifdef OSD_WINDOWS
117 if (IsDebuggerPresent())
118 {
119 win_output_debug_string_utf8(message);
120 DebugBreak();
121 }
122 else if (s_debugger_stack_crawler != nullptr)
123 (*s_debugger_stack_crawler)();
124 #else
125 if (IsDebuggerPresent())
126 {
127 OutputDebugStringA(message);
128 DebugBreak();
129 }
130 #endif
131 }
132
133 //============================================================
134 // get_clipboard_text_by_format
135 //============================================================
136
get_clipboard_text_by_format(std::string & result_text,UINT format,std::string (* convert)(LPCVOID data))137 static bool get_clipboard_text_by_format(std::string &result_text, UINT format, std::string (*convert)(LPCVOID data))
138 {
139 bool result = false;
140 HANDLE data_handle;
141 LPVOID data;
142
143 // check to see if this format is available
144 if (IsClipboardFormatAvailable(format))
145 {
146 // open the clipboard
147 if (OpenClipboard(nullptr))
148 {
149 // try to access clipboard data
150 data_handle = GetClipboardData(format);
151 if (data_handle != nullptr)
152 {
153 // lock the data
154 data = GlobalLock(data_handle);
155 if (data != nullptr)
156 {
157 // invoke the convert
158 result_text = (*convert)(data);
159 result = true;
160
161 // unlock the data
162 GlobalUnlock(data_handle);
163 }
164 }
165
166 // close out the clipboard
167 CloseClipboard();
168 }
169 }
170 return result;
171 }
172
173 //============================================================
174 // convert_wide
175 //============================================================
176
convert_wide(LPCVOID data)177 static std::string convert_wide(LPCVOID data)
178 {
179 return osd::text::from_wstring((LPCWSTR) data);
180 }
181
182 //============================================================
183 // convert_ansi
184 //============================================================
185
convert_ansi(LPCVOID data)186 static std::string convert_ansi(LPCVOID data)
187 {
188 return osd::text::from_astring((LPCSTR) data);
189 }
190
191 //============================================================
192 // osd_get_clipboard_text
193 //============================================================
194
osd_get_clipboard_text()195 std::string osd_get_clipboard_text()
196 {
197 std::string result;
198
199 // try to access unicode text
200 if (!get_clipboard_text_by_format(result, CF_UNICODETEXT, convert_wide))
201 {
202 // try to access ANSI text
203 get_clipboard_text_by_format(result, CF_TEXT, convert_ansi);
204 }
205
206 return result;
207 }
208
209 //============================================================
210 // osd_getpid
211 //============================================================
212
osd_getpid()213 int osd_getpid()
214 {
215 return GetCurrentProcessId();
216 }
217
218 //============================================================
219 // osd_dynamic_bind
220 //============================================================
221
222 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
223 // for classic desktop applications
224 #define load_library(filename) LoadLibrary(filename)
225 #else
226 // for Windows Store universal applications
227 #define load_library(filename) LoadPackagedLibrary(filename, 0)
228 #endif
229
230 namespace osd {
231 class dynamic_module_win32_impl : public dynamic_module
232 {
233 public:
dynamic_module_win32_impl(std::vector<std::string> & libraries)234 dynamic_module_win32_impl(std::vector<std::string> &libraries)
235 : m_module(nullptr)
236 {
237 m_libraries = libraries;
238 }
239
~dynamic_module_win32_impl()240 virtual ~dynamic_module_win32_impl() override
241 {
242 if (m_module != nullptr)
243 FreeLibrary(m_module);
244 };
245
246 protected:
get_symbol_address(char const * symbol)247 virtual generic_fptr_t get_symbol_address(char const *symbol) override
248 {
249 /*
250 * given a list of libraries, if a first symbol is successfully loaded from
251 * one of them, all additional symbols will be loaded from the same library
252 */
253 if (m_module)
254 {
255 return reinterpret_cast<generic_fptr_t>(GetProcAddress(m_module, symbol));
256 }
257
258 for (auto const &library : m_libraries)
259 {
260 osd::text::tstring tempstr = osd::text::to_tstring(library);
261 HMODULE module = load_library(tempstr.c_str());
262
263 if (module != nullptr)
264 {
265 auto function = reinterpret_cast<generic_fptr_t>(GetProcAddress(module, symbol));
266
267 if (function != nullptr)
268 {
269 m_module = module;
270 return function;
271 }
272 else
273 {
274 FreeLibrary(module);
275 }
276 }
277 }
278
279 return nullptr;
280 }
281
282 private:
283 std::vector<std::string> m_libraries;
284 HMODULE m_module;
285 };
286
open(std::vector<std::string> && names)287 dynamic_module::ptr dynamic_module::open(std::vector<std::string> &&names)
288 {
289 return std::make_unique<dynamic_module_win32_impl>(names);
290 }
291
292 } // namespace osd
293