]> git.ipfire.org Git - thirdparty/gcc.git/blame - libjava/win32.cc
Fix typo in docs.
[thirdparty/gcc.git] / libjava / win32.cc
CommitLineData
b8fe3c1e
AM
1// win32.cc - Helper functions for Microsoft-flavored OSs.
2
a191802c 3/* Copyright (C) 2002, 2003 Free Software Foundation
b8fe3c1e
AM
4
5 This file is part of libgcj.
6
7This software is copyrighted work licensed under the terms of the
8Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9details. */
10
11#include <config.h>
a191802c 12#include <platform.h>
8eeda6e0 13#include <sys/timeb.h>
455cd615 14#include <stdlib.h>
ef050c9e 15#include <fcntl.h>
b8fe3c1e 16
1febeb40 17#include <java/lang/ArithmeticException.h>
5c144158
ME
18#include <java/lang/UnsupportedOperationException.h>
19#include <java/io/IOException.h>
20#include <java/net/SocketException.h>
455cd615 21#include <java/util/Properties.h>
73272ce6
TT
22
23static LONG CALLBACK
b8fe3c1e
AM
24win32_exception_handler (LPEXCEPTION_POINTERS e)
25{
26 if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
27 _Jv_ThrowNullPointerException();
28 else if (e->ExceptionRecord->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO)
29 throw new java::lang::ArithmeticException;
30 else
31 return EXCEPTION_CONTINUE_SEARCH;
32}
73272ce6 33
c068c638
AH
34// Platform-specific executable name
35static char exec_name[MAX_PATH];
36 // initialized in _Jv_platform_initialize()
37
38const char *_Jv_ThisExecutable (void)
39{
40 return exec_name;
41}
42
5c144158
ME
43// Helper classes and methods implementation
44
83c02e38
ME
45#ifdef MINGW_LIBGCJ_UNICODE
46
47// We're using the OS W (UNICODE) API, which means that we're speaking
48// the same language....
49jstring
50_Jv_Win32NewString (LPCTSTR pcsz)
51{
52 return JvNewString ((jchar*) pcsz, _tcslen (pcsz));
53}
54
55#else
56
57// We're using the OS A functions, which means we need to translate between
58// UNICODE and the native character set.
59
60// First, let's set up some helper translation functions....
61
62// Converts the native string to any specified jstring, returning the
63// length of the jstring. If the specified jstring is null, we simply
64// compute and return the length.
65static int nativeToUnicode(LPCSTR pcsz, jstring jstr = 0)
66{
67 jchar* buf = 0;
68 int len = 0;
69 if (jstr)
70 {
71 len = jstr->length();
72 buf = JvGetStringChars(jstr);
73 }
74 return ::MultiByteToWideChar(GetACP(), 0, pcsz,
75 strlen(pcsz), (LPWSTR) buf, len);
76}
77
78// Does the inverse of nativeToUnicode, with the same calling semantics.
79static int unicodeToNative(jstring jstr, LPSTR buf, int buflen)
80{
81 return ::WideCharToMultiByte(GetACP(), 0, (LPWSTR) JvGetStringChars(jstr),
82 jstr->length(), buf, buflen, NULL, NULL);
83}
84
85// Convenience function when the caller only wants to compute the length
86// of the native string.
87static int unicodeToNative(jstring jstr)
88{
89 return unicodeToNative(jstr, 0, 0);
90}
91
92jstring
93_Jv_Win32NewString (LPCTSTR pcsz)
94{
95 // Compute the length, allocate the jstring, then perform the conversion.
96 int len = nativeToUnicode(pcsz);
97 jstring jstr = JvAllocString(len);
98 nativeToUnicode(pcsz, jstr);
99 return jstr;
100}
101
102#endif // MINGW_LIBGCJ_UNICODE
103
104// class _Jv_Win32TempString
105_Jv_Win32TempString::_Jv_Win32TempString(jstring jstr):
106 buf_(0)
107{
108 if (jstr == 0)
109 return;
110
111 // We need space for the string length plus a null terminator.
112 // Determine whether to use our stack-allocated buffer or a heap-
113 // allocated one.
114#ifdef MINGW_LIBGCJ_UNICODE
115 // A UNICODE character is a UNICODE character is a UNICODE character....
116 int len = jstr->length();
117#else
118 // Compute the length of the native character string.
119 int len = unicodeToNative(jstr);
120#endif // MINGW_LIBGCJ_UNICODE
121
122 int bytesNeeded = (len + 1) * sizeof(TCHAR);
123 if (bytesNeeded <= (int) sizeof(stackbuf_))
124 buf_ = stackbuf_;
125 else
126 buf_ = (LPTSTR) _Jv_Malloc(bytesNeeded);
127
128#ifdef MINGW_LIBGCJ_UNICODE
129 // Copy the UNICODE characters to our buffer.
130 _tcsncpy(buf_, (LPCTSTR) JvGetStringChars (jstr), len);
131#else
132 // Convert the UNICODE string to a native one.
133 unicodeToNative(jstr, buf_, len);
134#endif // MINGW_LIBGCJ_UNICODE
135
136 buf_[len] = 0;
137}
138
139_Jv_Win32TempString::~_Jv_Win32TempString()
140{
141 if (buf_ && buf_ != stackbuf_)
142 _Jv_Free (buf_);
143}
144
5c144158 145// class WSAEventWrapper
5cd4d463
ME
146WSAEventWrapper::WSAEventWrapper ():
147 m_hEvent(0),
148 m_fd(0),
149 m_dwSelFlags(0)
150{}
151
5c144158
ME
152WSAEventWrapper::WSAEventWrapper (int fd, DWORD dwSelFlags):
153 m_hEvent(0),
5cd4d463
ME
154 m_fd(0),
155 m_dwSelFlags(0)
156{
157 init(fd, dwSelFlags);
158}
159
160void WSAEventWrapper::init(int fd, DWORD dwSelFlags)
5c144158 161{
5cd4d463
ME
162 m_fd = fd;
163 m_dwSelFlags = dwSelFlags;
5c144158
ME
164 m_hEvent = WSACreateEvent ();
165 if (dwSelFlags)
166 WSAEventSelect(fd, m_hEvent, dwSelFlags);
167}
168
169WSAEventWrapper::~WSAEventWrapper ()
170{
171 if (m_dwSelFlags)
172 {
173 WSAEventSelect(m_fd, m_hEvent, 0);
174 if (m_dwSelFlags & (FD_ACCEPT | FD_CONNECT))
175 {
176 // Set the socket back to non-blocking mode.
177 // Ignore any error since we're in a destructor.
178 unsigned long lSockOpt = 0L;
179 // blocking mode
180 ::ioctlsocket (m_fd, FIONBIO, &lSockOpt);
181 }
182 }
183 WSACloseEvent (m_hEvent);
184}
185
186// Error string text.
187jstring
188_Jv_WinStrError (LPCTSTR lpszPrologue, int nErrorCode)
189{
190 LPTSTR lpMsgBuf = 0;
191
192 DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
193 FORMAT_MESSAGE_FROM_SYSTEM |
194 FORMAT_MESSAGE_IGNORE_INSERTS;
195
196 FormatMessage (dwFlags,
197 NULL,
198 (DWORD) nErrorCode,
199 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
200 (LPTSTR) &lpMsgBuf,
201 0,
202 NULL);
203
204 jstring ret;
205 if (lpszPrologue)
206 {
207 LPTSTR lpszTemp =
83c02e38
ME
208 (LPTSTR) _Jv_Malloc ((_tcslen (lpszPrologue) +
209 _tcslen (lpMsgBuf) + 3) * sizeof(TCHAR) );
210 _tcscpy (lpszTemp, lpszPrologue);
211 _tcscat (lpszTemp, _T(": "));
212 _tcscat (lpszTemp, lpMsgBuf);
213 ret = _Jv_Win32NewString (lpszTemp);
214 _Jv_Free (lpszTemp);
5c144158
ME
215 }
216 else
217 {
83c02e38 218 ret = _Jv_Win32NewString (lpMsgBuf);
5c144158
ME
219 }
220
221 LocalFree(lpMsgBuf);
222 return ret;
223}
224
225jstring
226_Jv_WinStrError (int nErrorCode)
227{
228 return _Jv_WinStrError (0, nErrorCode);
229}
230
231void _Jv_ThrowIOException (DWORD dwErrorCode)
232{
233 throw new java::io::IOException (_Jv_WinStrError (dwErrorCode));
234}
235
236void _Jv_ThrowIOException()
237{
238 DWORD dwErrorCode = WSAGetLastError ();
239 _Jv_ThrowIOException (dwErrorCode);
240}
241
242void _Jv_ThrowSocketException (DWORD dwErrorCode)
243{
244 throw new java::net::SocketException (_Jv_WinStrError (dwErrorCode));
245}
246
247void _Jv_ThrowSocketException()
248{
249 DWORD dwErrorCode = WSAGetLastError ();
250 _Jv_ThrowSocketException (dwErrorCode);
251}
252
73272ce6
TT
253// Platform-specific VM initialization.
254void
255_Jv_platform_initialize (void)
256{
257 // Initialise winsock for networking
258 WSADATA data;
5b5662ee 259 if (WSAStartup (MAKEWORD (2, 2), &data))
83c02e38 260 MessageBox (NULL, _T("Error initialising winsock library."), _T("Error"),
5c144158
ME
261 MB_OK | MB_ICONEXCLAMATION);
262
73272ce6
TT
263 // Install exception handler
264 SetUnhandledExceptionFilter (win32_exception_handler);
5c144158 265
83c02e38
ME
266 // Initialize our executable name.
267 // FIXME: We unconditionally use the ANSI function because
268 // _Jv_ThisExecutable returns a const char*. We should really
269 // change _Jv_ThisExecutable to return a jstring.
270 GetModuleFileNameA(NULL, exec_name, sizeof(exec_name));
73272ce6 271}
b32d2321
AM
272
273// gettimeofday implementation.
8eeda6e0
AM
274jlong
275_Jv_platform_gettimeofday ()
b32d2321 276{
8eeda6e0
AM
277 struct timeb t;
278 ftime (&t);
bb0774f3 279 return t.time * 1000LL + t.millitm;
b32d2321
AM
280}
281
9268f1c0
AM
282// The following definitions "fake out" mingw to think that -mthreads
283// was enabled and that mingwthr.dll was linked. GCJ-compiled
284// applications don't need this helper library because we can safely
285// detect thread death (return from Thread.run()).
286
287int _CRT_MT = 1;
288
289extern "C" int
290__mingwthr_key_dtor (DWORD, void (*) (void *))
291{
292 // FIXME: for now we do nothing; this causes a memory leak of
293 // approximately 24 bytes per thread created.
294 return 0;
295}
455cd615 296
83c02e38 297static bool dirExists (LPCTSTR dir)
748e241e
ME
298{
299 DWORD dwAttrs = ::GetFileAttributes (dir);
300 return dwAttrs != 0xFFFFFFFF &&
301 (dwAttrs & FILE_ATTRIBUTE_DIRECTORY) != 0;
302}
303
83c02e38 304static void getUserHome(LPTSTR userHome, LPCTSTR userId)
748e241e 305{
83c02e38 306 LPTSTR uh = _tgetenv (_T("USERPROFILE"));
748e241e
ME
307 if (uh)
308 {
83c02e38 309 _tcscpy(userHome, uh);
748e241e
ME
310 }
311 else
312 {
313 // Make a half-hearted attempt to support this
314 // legacy version of Windows. Try %WINDIR%\Profiles\%USERNAME%
315 // and failing this, use %WINDIR%.
316 //
317 // See:http://java.sun.com/docs/books/tutorial/security1.2/summary/files.html#UserPolicy
318 //
319 // To do this correctly, we'd have to factor in the
320 // Windows version, but if we did that, then this attempt
321 // wouldn't be half-hearted.
83c02e38 322 TCHAR userHomePath[MAX_PATH], winHome[MAX_PATH];
748e241e
ME
323 ::GetWindowsDirectory(winHome, MAX_PATH);
324 // assume this call always succeeds
325
83c02e38 326 _stprintf(userHomePath, _T("%s\\Profiles\\%s"), winHome, userId);
748e241e 327 if (dirExists (userHomePath))
83c02e38 328 _tcscpy(userHome, userHomePath);
748e241e 329 else
83c02e38 330 _tcscpy(userHome, winHome);
748e241e
ME
331 }
332}
333
455cd615
AK
334// Set platform-specific System properties.
335void
336_Jv_platform_initProperties (java::util::Properties* newprops)
337{
338 // A convenience define.
339#define SET(Prop,Val) \
83c02e38 340 newprops->put(JvNewStringLatin1 (Prop), _Jv_Win32NewString (Val))
455cd615 341
83c02e38
ME
342 SET ("file.separator", _T("\\"));
343 SET ("path.separator", _T(";"));
344 SET ("line.separator", _T("\r\n"));
455cd615
AK
345
346 // Use GetCurrentDirectory to set 'user.dir'.
347 DWORD buflen = MAX_PATH;
83c02e38 348 TCHAR buffer[buflen];
455cd615
AK
349 if (buffer != NULL)
350 {
351 if (GetCurrentDirectory (buflen, buffer))
5c144158 352 SET ("user.dir", buffer);
94ed0002
AK
353
354 if (GetTempPath (buflen, buffer))
5c144158 355 SET ("java.io.tmpdir", buffer);
455cd615 356 }
5c144158 357
455cd615
AK
358 // Use GetUserName to set 'user.name'.
359 buflen = 257; // UNLEN + 1
83c02e38 360 TCHAR userName[buflen];
748e241e
ME
361 if (GetUserName (userName, &buflen))
362 SET ("user.name", userName);
363
364 // Set user.home
83c02e38 365 TCHAR userHome[MAX_PATH];
748e241e
ME
366 getUserHome(userHome, userName);
367 SET ("user.home", userHome);
455cd615
AK
368
369 // Get and set some OS info.
370 OSVERSIONINFO osvi;
371 ZeroMemory (&osvi, sizeof(OSVERSIONINFO));
372 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
373 if (GetVersionEx (&osvi))
374 {
455cd615
AK
375 if (buffer != NULL)
376 {
83c02e38 377 _stprintf (buffer, _T("%d.%d"), (int) osvi.dwMajorVersion,
5c144158 378 (int) osvi.dwMinorVersion);
455cd615 379 SET ("os.version", buffer);
455cd615
AK
380 }
381
382 switch (osvi.dwPlatformId)
383 {
384 case VER_PLATFORM_WIN32_WINDOWS:
385 if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
83c02e38 386 SET ("os.name", _T("Windows 95"));
455cd615 387 else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
83c02e38 388 SET ("os.name", _T("Windows 98"));
455cd615 389 else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
83c02e38 390 SET ("os.name", _T("Windows Me"));
455cd615 391 else
83c02e38 392 SET ("os.name", _T("Windows ??"));
455cd615
AK
393 break;
394
395 case VER_PLATFORM_WIN32_NT:
396 if (osvi.dwMajorVersion <= 4 )
83c02e38 397 SET ("os.name", _T("Windows NT"));
455cd615 398 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
83c02e38 399 SET ("os.name", _T("Windows 2000"));
455cd615 400 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
83c02e38 401 SET ("os.name", _T("Windows XP"));
455cd615 402 else
83c02e38 403 SET ("os.name", _T("Windows NT ??"));
455cd615
AK
404 break;
405
406 default:
83c02e38 407 SET ("os.name", _T("Windows UNKNOWN"));
455cd615
AK
408 break;
409 }
410 }
411
412 // Set the OS architecture.
413 SYSTEM_INFO si;
414 GetSystemInfo (&si);
14a5a676 415 switch (si.wProcessorArchitecture)
455cd615 416 {
14a5a676 417 case PROCESSOR_ARCHITECTURE_INTEL:
83c02e38 418 SET ("os.arch", _T("x86"));
455cd615 419 break;
14a5a676 420 case PROCESSOR_ARCHITECTURE_MIPS:
83c02e38 421 SET ("os.arch", _T("mips"));
455cd615 422 break;
14a5a676 423 case PROCESSOR_ARCHITECTURE_ALPHA:
83c02e38 424 SET ("os.arch", _T("alpha"));
455cd615 425 break;
83c02e38
ME
426 case PROCESSOR_ARCHITECTURE_PPC:
427 SET ("os.arch", _T("ppc"));
455cd615 428 break;
14a5a676 429 case PROCESSOR_ARCHITECTURE_IA64:
83c02e38 430 SET ("os.arch", _T("ia64"));
455cd615 431 break;
14a5a676 432 case PROCESSOR_ARCHITECTURE_UNKNOWN:
455cd615 433 default:
83c02e38 434 SET ("os.arch", _T("unknown"));
455cd615
AK
435 break;
436 }
437}
c2a6704f
AM
438
439/* Store up to SIZE return address of the current program state in
440 ARRAY and return the exact number of values stored. */
441int
442backtrace (void **__array, int __size)
443{
444 register void *_ebp __asm__ ("ebp");
445 register void *_esp __asm__ ("esp");
446 unsigned int *rfp;
447
448 int i=0;
449 for (rfp = *(unsigned int**)_ebp;
450 rfp && i < __size;
451 rfp = *(unsigned int **)rfp)
452 {
453 int diff = *rfp - (unsigned int)rfp;
454 if ((void*)rfp < _esp || diff > 4 * 1024 || diff < 0) break;
455
456 __array[i++] = (void*)(rfp[1]-4);
457 }
458 return i;
459}
5c144158 460
ef050c9e
ME
461int
462_Jv_pipe (int filedes[2])
463{
464 return _pipe (filedes, 4096, _O_BINARY);
465}
bbf76ec0
ME
466
467void
468_Jv_platform_close_on_exec (HANDLE h)
469{
470 // Mark the handle as non-inheritable. This has
471 // no effect under Win9X.
472 SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0);
473}