1 // win32.cc - Helper functions for Microsoft-flavored OSs.
3 /* Copyright (C) 2002, 2003 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
13 #include <sys/timeb.h>
17 #include <java/lang/ArithmeticException.h>
18 #include <java/lang/UnsupportedOperationException.h>
19 #include <java/io/IOException.h>
20 #include <java/net/SocketException.h>
21 #include <java/util/Properties.h>
24 win32_exception_handler (LPEXCEPTION_POINTERS e
)
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
;
31 return EXCEPTION_CONTINUE_SEARCH
;
34 // Platform-specific executable name
35 static char exec_name
[MAX_PATH
];
36 // initialized in _Jv_platform_initialize()
38 const char *_Jv_ThisExecutable (void)
43 // Helper classes and methods implementation
45 #ifdef MINGW_LIBGCJ_UNICODE
47 // We're using the OS W (UNICODE) API, which means that we're speaking
48 // the same language....
50 _Jv_Win32NewString (LPCTSTR pcsz
)
52 return JvNewString ((jchar
*) pcsz
, _tcslen (pcsz
));
57 // We're using the OS A functions, which means we need to translate between
58 // UNICODE and the native character set.
60 // First, let's set up some helper translation functions....
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.
65 static int nativeToUnicode(LPCSTR pcsz
, jstring jstr
= 0)
72 buf
= JvGetStringChars(jstr
);
74 return ::MultiByteToWideChar(GetACP(), 0, pcsz
,
75 strlen(pcsz
), (LPWSTR
) buf
, len
);
78 // Does the inverse of nativeToUnicode, with the same calling semantics.
79 static int unicodeToNative(jstring jstr
, LPSTR buf
, int buflen
)
81 return ::WideCharToMultiByte(GetACP(), 0, (LPWSTR
) JvGetStringChars(jstr
),
82 jstr
->length(), buf
, buflen
, NULL
, NULL
);
85 // Convenience function when the caller only wants to compute the length
86 // of the native string.
87 static int unicodeToNative(jstring jstr
)
89 return unicodeToNative(jstr
, 0, 0);
93 _Jv_Win32NewString (LPCTSTR pcsz
)
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
);
102 #endif // MINGW_LIBGCJ_UNICODE
104 // class _Jv_Win32TempString
105 _Jv_Win32TempString::_Jv_Win32TempString(jstring jstr
):
111 // We need space for the string length plus a null terminator.
112 // Determine whether to use our stack-allocated buffer or a heap-
114 #ifdef MINGW_LIBGCJ_UNICODE
115 // A UNICODE character is a UNICODE character is a UNICODE character....
116 int len
= jstr
->length();
118 // Compute the length of the native character string.
119 int len
= unicodeToNative(jstr
);
120 #endif // MINGW_LIBGCJ_UNICODE
122 int bytesNeeded
= (len
+ 1) * sizeof(TCHAR
);
123 if (bytesNeeded
<= (int) sizeof(stackbuf_
))
126 buf_
= (LPTSTR
) _Jv_Malloc(bytesNeeded
);
128 #ifdef MINGW_LIBGCJ_UNICODE
129 // Copy the UNICODE characters to our buffer.
130 _tcsncpy(buf_
, (LPCTSTR
) JvGetStringChars (jstr
), len
);
132 // Convert the UNICODE string to a native one.
133 unicodeToNative(jstr
, buf_
, len
);
134 #endif // MINGW_LIBGCJ_UNICODE
139 _Jv_Win32TempString::~_Jv_Win32TempString()
141 if (buf_
&& buf_
!= stackbuf_
)
145 // class WSAEventWrapper
146 WSAEventWrapper::WSAEventWrapper ():
152 WSAEventWrapper::WSAEventWrapper (int fd
, DWORD dwSelFlags
):
157 init(fd
, dwSelFlags
);
160 void WSAEventWrapper::init(int fd
, DWORD dwSelFlags
)
163 m_dwSelFlags
= dwSelFlags
;
164 m_hEvent
= WSACreateEvent ();
166 WSAEventSelect(fd
, m_hEvent
, dwSelFlags
);
169 WSAEventWrapper::~WSAEventWrapper ()
173 WSAEventSelect(m_fd
, m_hEvent
, 0);
174 if (m_dwSelFlags
& (FD_ACCEPT
| FD_CONNECT
))
176 // Set the socket back to non-blocking mode.
177 // Ignore any error since we're in a destructor.
178 unsigned long lSockOpt
= 0L;
180 ::ioctlsocket (m_fd
, FIONBIO
, &lSockOpt
);
183 WSACloseEvent (m_hEvent
);
186 // Error string text.
188 _Jv_WinStrError (LPCTSTR lpszPrologue
, int nErrorCode
)
192 DWORD dwFlags
= FORMAT_MESSAGE_ALLOCATE_BUFFER
|
193 FORMAT_MESSAGE_FROM_SYSTEM
|
194 FORMAT_MESSAGE_IGNORE_INSERTS
;
196 FormatMessage (dwFlags
,
199 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
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
);
218 ret
= _Jv_Win32NewString (lpMsgBuf
);
226 _Jv_WinStrError (int nErrorCode
)
228 return _Jv_WinStrError (0, nErrorCode
);
231 void _Jv_ThrowIOException (DWORD dwErrorCode
)
233 throw new java::io::IOException (_Jv_WinStrError (dwErrorCode
));
236 void _Jv_ThrowIOException()
238 DWORD dwErrorCode
= WSAGetLastError ();
239 _Jv_ThrowIOException (dwErrorCode
);
242 void _Jv_ThrowSocketException (DWORD dwErrorCode
)
244 throw new java::net::SocketException (_Jv_WinStrError (dwErrorCode
));
247 void _Jv_ThrowSocketException()
249 DWORD dwErrorCode
= WSAGetLastError ();
250 _Jv_ThrowSocketException (dwErrorCode
);
253 // Platform-specific VM initialization.
255 _Jv_platform_initialize (void)
257 // Initialise winsock for networking
259 if (WSAStartup (MAKEWORD (2, 2), &data
))
260 MessageBox (NULL
, _T("Error initialising winsock library."), _T("Error"),
261 MB_OK
| MB_ICONEXCLAMATION
);
263 // Install exception handler
264 SetUnhandledExceptionFilter (win32_exception_handler
);
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
));
273 // gettimeofday implementation.
275 _Jv_platform_gettimeofday ()
279 return t
.time
* 1000LL + t
.millitm
;
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()).
290 __mingwthr_key_dtor (DWORD
, void (*) (void *))
292 // FIXME: for now we do nothing; this causes a memory leak of
293 // approximately 24 bytes per thread created.
297 static bool dirExists (LPCTSTR dir
)
299 DWORD dwAttrs
= ::GetFileAttributes (dir
);
300 return dwAttrs
!= 0xFFFFFFFF &&
301 (dwAttrs
& FILE_ATTRIBUTE_DIRECTORY
) != 0;
304 static void getUserHome(LPTSTR userHome
, LPCTSTR userId
)
306 LPTSTR uh
= _tgetenv (_T("USERPROFILE"));
309 _tcscpy(userHome
, uh
);
313 // Make a half-hearted attempt to support this
314 // legacy version of Windows. Try %WINDIR%\Profiles\%USERNAME%
315 // and failing this, use %WINDIR%.
317 // See:http://java.sun.com/docs/books/tutorial/security1.2/summary/files.html#UserPolicy
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.
322 TCHAR userHomePath
[MAX_PATH
], winHome
[MAX_PATH
];
323 ::GetWindowsDirectory(winHome
, MAX_PATH
);
324 // assume this call always succeeds
326 _stprintf(userHomePath
, _T("%s\\Profiles\\%s"), winHome
, userId
);
327 if (dirExists (userHomePath
))
328 _tcscpy(userHome
, userHomePath
);
330 _tcscpy(userHome
, winHome
);
334 // Set platform-specific System properties.
336 _Jv_platform_initProperties (java::util::Properties
* newprops
)
338 // A convenience define.
339 #define SET(Prop,Val) \
340 newprops->put(JvNewStringLatin1 (Prop), _Jv_Win32NewString (Val))
342 SET ("file.separator", _T("\\"));
343 SET ("path.separator", _T(";"));
344 SET ("line.separator", _T("\r\n"));
346 // Use GetCurrentDirectory to set 'user.dir'.
347 DWORD buflen
= MAX_PATH
;
348 TCHAR buffer
[buflen
];
351 if (GetCurrentDirectory (buflen
, buffer
))
352 SET ("user.dir", buffer
);
354 if (GetTempPath (buflen
, buffer
))
355 SET ("java.io.tmpdir", buffer
);
358 // Use GetUserName to set 'user.name'.
359 buflen
= 257; // UNLEN + 1
360 TCHAR userName
[buflen
];
361 if (GetUserName (userName
, &buflen
))
362 SET ("user.name", userName
);
365 TCHAR userHome
[MAX_PATH
];
366 getUserHome(userHome
, userName
);
367 SET ("user.home", userHome
);
369 // Get and set some OS info.
371 ZeroMemory (&osvi
, sizeof(OSVERSIONINFO
));
372 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
373 if (GetVersionEx (&osvi
))
377 _stprintf (buffer
, _T("%d.%d"), (int) osvi
.dwMajorVersion
,
378 (int) osvi
.dwMinorVersion
);
379 SET ("os.version", buffer
);
382 switch (osvi
.dwPlatformId
)
384 case VER_PLATFORM_WIN32_WINDOWS
:
385 if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 0)
386 SET ("os.name", _T("Windows 95"));
387 else if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 10)
388 SET ("os.name", _T("Windows 98"));
389 else if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 90)
390 SET ("os.name", _T("Windows Me"));
392 SET ("os.name", _T("Windows ??"));
395 case VER_PLATFORM_WIN32_NT
:
396 if (osvi
.dwMajorVersion
<= 4 )
397 SET ("os.name", _T("Windows NT"));
398 else if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 0)
399 SET ("os.name", _T("Windows 2000"));
400 else if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 1)
401 SET ("os.name", _T("Windows XP"));
403 SET ("os.name", _T("Windows NT ??"));
407 SET ("os.name", _T("Windows UNKNOWN"));
412 // Set the OS architecture.
415 switch (si
.wProcessorArchitecture
)
417 case PROCESSOR_ARCHITECTURE_INTEL
:
418 SET ("os.arch", _T("x86"));
420 case PROCESSOR_ARCHITECTURE_MIPS
:
421 SET ("os.arch", _T("mips"));
423 case PROCESSOR_ARCHITECTURE_ALPHA
:
424 SET ("os.arch", _T("alpha"));
426 case PROCESSOR_ARCHITECTURE_PPC
:
427 SET ("os.arch", _T("ppc"));
429 case PROCESSOR_ARCHITECTURE_IA64
:
430 SET ("os.arch", _T("ia64"));
432 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
434 SET ("os.arch", _T("unknown"));
439 /* Store up to SIZE return address of the current program state in
440 ARRAY and return the exact number of values stored. */
442 backtrace (void **__array
, int __size
)
444 register void *_ebp
__asm__ ("ebp");
445 register void *_esp
__asm__ ("esp");
449 for (rfp
= *(unsigned int**)_ebp
;
451 rfp
= *(unsigned int **)rfp
)
453 int diff
= *rfp
- (unsigned int)rfp
;
454 if ((void*)rfp
< _esp
|| diff
> 4 * 1024 || diff
< 0) break;
456 __array
[i
++] = (void*)(rfp
[1]-4);
462 _Jv_pipe (int filedes
[2])
464 return _pipe (filedes
, 4096, _O_BINARY
);
468 _Jv_platform_close_on_exec (HANDLE h
)
470 // Mark the handle as non-inheritable. This has
471 // no effect under Win9X.
472 SetHandleInformation (h
, HANDLE_FLAG_INHERIT
, 0);