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>
16 #include <java/lang/ArithmeticException.h>
17 #include <java/lang/UnsupportedOperationException.h>
18 #include <java/io/IOException.h>
19 #include <java/net/SocketException.h>
20 #include <java/util/Properties.h>
23 win32_exception_handler (LPEXCEPTION_POINTERS e
)
25 if (e
->ExceptionRecord
->ExceptionCode
== EXCEPTION_ACCESS_VIOLATION
)
26 _Jv_ThrowNullPointerException();
27 else if (e
->ExceptionRecord
->ExceptionCode
== EXCEPTION_INT_DIVIDE_BY_ZERO
)
28 throw new java::lang::ArithmeticException
;
30 return EXCEPTION_CONTINUE_SEARCH
;
33 // Platform-specific executable name
34 static char exec_name
[MAX_PATH
];
35 // initialized in _Jv_platform_initialize()
37 const char *_Jv_ThisExecutable (void)
42 // Helper classes and methods implementation
44 // class WSAEventWrapper
45 WSAEventWrapper::WSAEventWrapper (int fd
, DWORD dwSelFlags
):
48 m_dwSelFlags(dwSelFlags
)
50 m_hEvent
= WSACreateEvent ();
52 WSAEventSelect(fd
, m_hEvent
, dwSelFlags
);
55 WSAEventWrapper::~WSAEventWrapper ()
59 WSAEventSelect(m_fd
, m_hEvent
, 0);
60 if (m_dwSelFlags
& (FD_ACCEPT
| FD_CONNECT
))
62 // Set the socket back to non-blocking mode.
63 // Ignore any error since we're in a destructor.
64 unsigned long lSockOpt
= 0L;
66 ::ioctlsocket (m_fd
, FIONBIO
, &lSockOpt
);
69 WSACloseEvent (m_hEvent
);
74 _Jv_WinStrError (LPCTSTR lpszPrologue
, int nErrorCode
)
78 DWORD dwFlags
= FORMAT_MESSAGE_ALLOCATE_BUFFER
|
79 FORMAT_MESSAGE_FROM_SYSTEM
|
80 FORMAT_MESSAGE_IGNORE_INSERTS
;
82 FormatMessage (dwFlags
,
85 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
94 (LPTSTR
) _Jv_Malloc (strlen (lpszPrologue
) +
95 strlen (lpMsgBuf
) + 3);
96 strcpy (lpszTemp
, lpszPrologue
);
97 strcat (lpszTemp
, ": ");
98 strcat (lpszTemp
, lpMsgBuf
);
99 ret
= JvNewStringLatin1 (lpszTemp
);
103 ret
= JvNewStringLatin1 (lpMsgBuf
);
111 _Jv_WinStrError (int nErrorCode
)
113 return _Jv_WinStrError (0, nErrorCode
);
116 void _Jv_ThrowIOException (DWORD dwErrorCode
)
118 throw new java::io::IOException (_Jv_WinStrError (dwErrorCode
));
121 void _Jv_ThrowIOException()
123 DWORD dwErrorCode
= WSAGetLastError ();
124 _Jv_ThrowIOException (dwErrorCode
);
127 void _Jv_ThrowSocketException (DWORD dwErrorCode
)
129 throw new java::net::SocketException (_Jv_WinStrError (dwErrorCode
));
132 void _Jv_ThrowSocketException()
134 DWORD dwErrorCode
= WSAGetLastError ();
135 _Jv_ThrowSocketException (dwErrorCode
);
138 // Platform-specific VM initialization.
140 _Jv_platform_initialize (void)
142 // Initialise winsock for networking
144 if (WSAStartup (MAKEWORD (1, 1), &data
))
145 MessageBox (NULL
, "Error initialising winsock library.", "Error",
146 MB_OK
| MB_ICONEXCLAMATION
);
148 // Install exception handler
149 SetUnhandledExceptionFilter (win32_exception_handler
);
151 // Initialize our executable name
152 GetModuleFileName(NULL
, exec_name
, sizeof(exec_name
));
155 // gettimeofday implementation.
157 _Jv_platform_gettimeofday ()
161 return t
.time
* 1000LL + t
.millitm
;
164 // The following definitions "fake out" mingw to think that -mthreads
165 // was enabled and that mingwthr.dll was linked. GCJ-compiled
166 // applications don't need this helper library because we can safely
167 // detect thread death (return from Thread.run()).
172 __mingwthr_key_dtor (DWORD
, void (*) (void *))
174 // FIXME: for now we do nothing; this causes a memory leak of
175 // approximately 24 bytes per thread created.
179 // Set platform-specific System properties.
181 _Jv_platform_initProperties (java::util::Properties
* newprops
)
183 // A convenience define.
184 #define SET(Prop,Val) \
185 newprops->put(JvNewStringLatin1 (Prop), JvNewStringLatin1 (Val))
187 SET ("file.separator", "\\");
188 SET ("path.separator", ";");
189 SET ("line.separator", "\r\n");
191 // Use GetCurrentDirectory to set 'user.dir'.
192 DWORD buflen
= MAX_PATH
;
193 char *buffer
= (char *) _Jv_MallocUnchecked (buflen
);
196 if (GetCurrentDirectory (buflen
, buffer
))
197 SET ("user.dir", buffer
);
199 if (GetTempPath (buflen
, buffer
))
200 SET ("java.io.tmpdir", buffer
);
205 // Use GetUserName to set 'user.name'.
206 buflen
= 257; // UNLEN + 1
207 buffer
= (char *) _Jv_MallocUnchecked (buflen
);
210 if (GetUserName (buffer
, &buflen
))
211 SET ("user.name", buffer
);
215 // According to the api documentation for 'GetWindowsDirectory()', the
216 // environmental variable HOMEPATH always specifies the user's home
217 // directory or a default directory. On the 3 windows machines I checked
218 // only 1 had it set. If it's not set, JDK1.3.1 seems to set it to
219 // the windows directory, so we'll do the same.
220 char *userHome
= NULL
;
221 if ((userHome
= ::getenv ("HOMEPATH")) == NULL
)
223 // Check HOME since it's what I use.
224 if ((userHome
= ::getenv ("HOME")) == NULL
)
226 // Not found - use the windows directory like JDK1.3.1 does.
227 char *winHome
= (char *) _Jv_MallocUnchecked (MAX_PATH
);
230 if (GetWindowsDirectory (winHome
, MAX_PATH
))
231 SET ("user.home", winHome
);
236 if (userHome
!= NULL
)
237 SET ("user.home", userHome
);
239 // Get and set some OS info.
241 ZeroMemory (&osvi
, sizeof(OSVERSIONINFO
));
242 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
243 if (GetVersionEx (&osvi
))
245 char *buffer
= (char *) _Jv_MallocUnchecked (30);
248 sprintf (buffer
, "%d.%d", (int) osvi
.dwMajorVersion
,
249 (int) osvi
.dwMinorVersion
);
250 SET ("os.version", buffer
);
254 switch (osvi
.dwPlatformId
)
256 case VER_PLATFORM_WIN32_WINDOWS
:
257 if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 0)
258 SET ("os.name", "Windows 95");
259 else if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 10)
260 SET ("os.name", "Windows 98");
261 else if (osvi
.dwMajorVersion
== 4 && osvi
.dwMinorVersion
== 90)
262 SET ("os.name", "Windows Me");
264 SET ("os.name", "Windows ??");
267 case VER_PLATFORM_WIN32_NT
:
268 if (osvi
.dwMajorVersion
<= 4 )
269 SET ("os.name", "Windows NT");
270 else if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 0)
271 SET ("os.name", "Windows 2000");
272 else if (osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 1)
273 SET ("os.name", "Windows XP");
275 SET ("os.name", "Windows NT ??");
279 SET ("os.name", "Windows UNKNOWN");
284 // Set the OS architecture.
287 switch (si
.wProcessorArchitecture
)
289 case PROCESSOR_ARCHITECTURE_INTEL
:
290 SET ("os.arch", "x86");
292 case PROCESSOR_ARCHITECTURE_MIPS
:
293 SET ("os.arch", "mips");
295 case PROCESSOR_ARCHITECTURE_ALPHA
:
296 SET ("os.arch", "alpha");
298 case PROCESSOR_ARCHITECTURE_PPC
:
299 SET ("os.arch", "ppc");
301 case PROCESSOR_ARCHITECTURE_IA64
:
302 SET ("os.arch", "ia64");
304 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
306 SET ("os.arch", "unknown");
311 /* Store up to SIZE return address of the current program state in
312 ARRAY and return the exact number of values stored. */
314 backtrace (void **__array
, int __size
)
316 register void *_ebp
__asm__ ("ebp");
317 register void *_esp
__asm__ ("esp");
321 for (rfp
= *(unsigned int**)_ebp
;
323 rfp
= *(unsigned int **)rfp
)
325 int diff
= *rfp
- (unsigned int)rfp
;
326 if ((void*)rfp
< _esp
|| diff
> 4 * 1024 || diff
< 0) break;
328 __array
[i
++] = (void*)(rfp
[1]-4);
334 _Jv_select (int n
, fd_set
*readfds
, fd_set
*writefds
,
335 fd_set
*exceptfds
, struct timeval
*timeout
)
337 int r
= ::select (n
, readfds
, writefds
, exceptfds
, timeout
);
338 if (r
== SOCKET_ERROR
)
340 DWORD dwErrorCode
= WSAGetLastError ();
341 throw new java::io::IOException (_Jv_WinStrError (dwErrorCode
));