1 /** \file archdep_win32.c
2 * \brief Miscellaneous Windows-specific stuff
3 *
4 * \author Marco van den Heuvel <blackystardust68@yahoo.com>
5 */
6
7 /*
8 * This file is part of VICE, the Versatile Commodore Emulator.
9 * See README for copyright notice.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 * 02111-1307 USA.
25 *
26 */
27
28 #include "vice.h"
29
30 #include <stdio.h>
31 #include <glib.h>
32 #include <windows.h>
33 #ifdef HAVE_FCNTL_H
34 #include <fcntl.h>
35 #endif
36
37 #if defined(HAVE_IO_H) && !defined(WINMIPS)
38 #include <io.h>
39 #endif
40
41 #ifdef HAVE_PROCESS_H
42 #include <process.h>
43 #endif
44
45 #ifdef HAVE_SYS_STAT_H
46 #include <sys/stat.h>
47 #endif
48
49 #ifdef HAVE_SYS_TYPES_H
50 #include <sys/types.h>
51 #endif
52
53 #ifdef HAVE_UNISTD_H
54 #include <unistd.h>
55 #endif
56
57 #include "lib.h"
58 #include "util.h"
59
60 #include "debug_gtk3.h"
61
62 #include "archdep.h"
63
64 /* fix VICE userdir */
65 #ifdef VICEUSERDIR
66 # undef VICEUSERDIR
67 #endif
68 #define VICEUSERDIR "vice"
69
70 #if 0
71 /** \brief Path separator used in GLib code
72 */
73 static const gchar *path_separator = "\\";
74 #endif
75
76
77 /** \brief Write message to Windows debugger/logger
78 *
79 * param[in] level_string log level string
80 * param[in] txt log message
81 *
82 * \note Shamelessly copied from win32/archdep.c
83 *
84 * \return 0 on success, < 0 on failure
85 */
archdep_default_logger(const char * level_string,const char * txt)86 int archdep_default_logger(const char *level_string, const char *txt)
87 {
88 char *out = lib_msprintf("*** %s %s\n", level_string, txt);
89 OutputDebugString(out);
90 lib_free(out);
91 return 0;
92 }
93
94
archdep_shutdown(void)95 void archdep_shutdown(void)
96 {
97 /* free memory used by the exec path */
98 archdep_program_path_free();
99 /* free memory used by the exec name */
100 archdep_program_name_free();
101 /* free memory used by the boot path */
102 archdep_boot_path_free();
103 /* free memory used by the home path */
104 archdep_home_path_free();
105 /* free memory used by the config files path */
106 archdep_user_config_path_free();
107 /* free memory used by the sysfile pathlist */
108 archdep_default_sysfile_pathlist_free();
109
110 /* do we need this anymore? argv is guaranteed to exist during the program
111 * lifetime and we already set a reference to argv[0] with
112 * archdep_program_path_set_argv0() */
113 if (argv0 != NULL) {
114 lib_free(argv0);
115 argv0 = NULL;
116 }
117
118 /* archdep_network_shutdown(); */
119 }
120
121
archdep_mkstemp_fd(char ** filename,const char * mode)122 FILE *archdep_mkstemp_fd(char **filename, const char *mode)
123 {
124 char *tmp;
125 FILE *fd;
126
127 if (getenv("temp")) {
128 tmp = util_concat(getenv("temp"), tmpnam(NULL), NULL);
129 } else if (getenv("tmp")) {
130 tmp = util_concat(getenv("tmp"), tmpnam(NULL), NULL);
131 } else {
132 tmp = lib_stralloc(tmpnam(NULL));
133 }
134
135 fd = fopen(tmp, mode);
136
137 if (fd == NULL) {
138 return NULL;
139 }
140
141 *filename = tmp;
142
143 return fd;
144 }
145
146
147 /** \brief Spawn new process
148 *
149 * Shamelessly stolen from arch/sdl/archdep_win32.c
150 */
archdep_spawn(const char * name,char ** argv,char ** pstdout_redir,const char * stderr_redir)151 int archdep_spawn(const char *name, char **argv, char **pstdout_redir, const char *stderr_redir)
152 {
153 int new_stdout, new_stderr;
154 int old_stdout_mode, old_stderr_mode;
155 int old_stdout, old_stderr;
156 int retval;
157 char *stdout_redir = NULL;
158
159 if (pstdout_redir != NULL) {
160 if (*pstdout_redir == NULL) {
161 *pstdout_redir = archdep_tmpnam();
162 }
163 stdout_redir = *pstdout_redir;
164 }
165
166 new_stdout = new_stderr = old_stdout = old_stderr = -1;
167
168 /* Make sure we are in binary mode. */
169 old_stdout_mode = _setmode(STDOUT_FILENO, _O_BINARY);
170 old_stderr_mode = _setmode(STDERR_FILENO, _O_BINARY);
171
172 /* Redirect stdout and stderr as requested, saving the old
173 descriptors. */
174 if (stdout_redir != NULL) {
175 old_stdout = _dup(STDOUT_FILENO);
176 new_stdout = _open(stdout_redir, _O_WRONLY | _O_TRUNC | _O_CREAT, _S_IWRITE | _S_IREAD);
177 if (new_stdout == -1) {
178 log_error(LOG_DEFAULT, "open(\"%s\") failed: %s.", stdout_redir, strerror(errno));
179 retval = -1;
180 goto cleanup;
181 }
182 _dup2(new_stdout, STDOUT_FILENO);
183 }
184 if (stderr_redir != NULL) {
185 old_stderr = _dup(STDERR_FILENO);
186 new_stderr = _open(stderr_redir, _O_WRONLY | _O_TRUNC | _O_CREAT, _S_IWRITE | _S_IREAD);
187 if (new_stderr == -1) {
188 log_error(LOG_DEFAULT, "open(\"%s\") failed: %s.", stderr_redir, strerror(errno));
189 retval = -1;
190 goto cleanup;
191 }
192 _dup2(new_stderr, STDERR_FILENO);
193 }
194
195 /* Spawn the child process. */
196 retval = (int)_spawnvp(_P_WAIT, name, (const char **)argv);
197
198 cleanup:
199 if (old_stdout >= 0) {
200 _dup2(old_stdout, STDOUT_FILENO);
201 _close(old_stdout);
202 }
203 if (old_stderr >= 0) {
204 _dup2(old_stderr, STDERR_FILENO);
205 _close(old_stderr);
206 }
207 if (old_stdout_mode >= 0) {
208 _setmode(STDOUT_FILENO, old_stdout_mode);
209 }
210 if (old_stderr_mode >= 0) {
211 _setmode(STDERR_FILENO, old_stderr_mode);
212 }
213 if (new_stdout >= 0) {
214 _close(new_stdout);
215 }
216 if (new_stderr >= 0) {
217 _close(new_stderr);
218 }
219
220 return retval;
221 }
222
223 #if 0
224 /** \brief Create a unique temporary filename
225 *
226 * \return unique filename in the %TEMP% directory
227 */
228 char *archdep_tmpnam(void)
229 {
230 if (getenv("temp")) {
231 return util_concat(getenv("temp"), tmpnam(NULL), NULL);
232 } else if (getenv("tmp")) {
233 return util_concat(getenv("tmp"), tmpnam(NULL), NULL);
234 } else {
235 return lib_stralloc(tmpnam(NULL));
236 }
237 }
238 #endif
239
240 /* Provide a usleep replacement */
vice_usleep(uint64_t waitTime)241 void vice_usleep(uint64_t waitTime)
242 {
243 uint64_t time1 = 0, time2 = 0, freq = 0;
244
245 QueryPerformanceCounter((LARGE_INTEGER *) &time1);
246 QueryPerformanceFrequency((LARGE_INTEGER *)&freq);
247
248 do {
249 QueryPerformanceCounter((LARGE_INTEGER *) &time2);
250 } while((time2-time1) < waitTime);
251 }
252
is_windows_nt(void)253 int is_windows_nt(void)
254 {
255 OSVERSIONINFO os_version_info;
256
257 ZeroMemory(&os_version_info, sizeof(os_version_info));
258 os_version_info.dwOSVersionInfoSize = sizeof(os_version_info);
259
260 GetVersionEx(&os_version_info);
261
262 if (os_version_info.dwPlatformId == VER_PLATFORM_WIN32_NT) {
263 return 1;
264 }
265 return 0;
266 }
267
268
archdep_signals_init(int do_core_dumps)269 void archdep_signals_init(int do_core_dumps)
270 {
271 /* NOP */
272 }
273