OSDN Git Service

dfed8c436603c0317a2e60b3e309bb74047eb5fc
[pf3gnuchains/gcc-fork.git] / libjava / win32.cc
1 // win32.cc - Helper functions for Microsoft-flavored OSs.
2
3 /* Copyright (C) 2002, 2003  Free Software Foundation
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 #include <config.h>
12 #include <platform.h>
13 #include <sys/timeb.h>
14 #include <stdlib.h>
15 #include <fcntl.h>
16
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>
22
23 static LONG CALLBACK
24 win32_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 }
33
34 // Platform-specific executable name
35 static char exec_name[MAX_PATH];
36   // initialized in _Jv_platform_initialize()
37
38 const char *_Jv_ThisExecutable (void)
39 {
40   return exec_name;
41 }
42
43 // Helper classes and methods implementation
44   
45 // class WSAEventWrapper
46 WSAEventWrapper::WSAEventWrapper (int fd, DWORD dwSelFlags):
47   m_hEvent(0),
48   m_fd(fd),
49   m_dwSelFlags(dwSelFlags)
50 {
51   m_hEvent = WSACreateEvent ();
52   if (dwSelFlags)
53     WSAEventSelect(fd, m_hEvent, dwSelFlags);
54 }
55
56 WSAEventWrapper::~WSAEventWrapper ()
57 {
58   if (m_dwSelFlags)
59   {
60     WSAEventSelect(m_fd, m_hEvent, 0);
61     if (m_dwSelFlags & (FD_ACCEPT | FD_CONNECT))
62     {
63       // Set the socket back to non-blocking mode.
64       // Ignore any error since we're in a destructor.
65       unsigned long lSockOpt = 0L;
66         // blocking mode
67       ::ioctlsocket (m_fd, FIONBIO, &lSockOpt);
68     }
69   }
70   WSACloseEvent (m_hEvent);
71 }
72
73 // Error string text.
74 jstring
75 _Jv_WinStrError (LPCTSTR lpszPrologue, int nErrorCode)
76 {
77   LPTSTR lpMsgBuf = 0;
78
79   DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
80     FORMAT_MESSAGE_FROM_SYSTEM |
81     FORMAT_MESSAGE_IGNORE_INSERTS;
82
83   FormatMessage (dwFlags,
84     NULL,
85     (DWORD) nErrorCode,
86     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
87     (LPTSTR) &lpMsgBuf,
88     0,
89     NULL);
90
91   jstring ret;
92   if (lpszPrologue)
93     {
94       LPTSTR lpszTemp =
95         (LPTSTR) _Jv_Malloc (strlen (lpszPrologue) +
96           strlen (lpMsgBuf) + 3);
97       strcpy (lpszTemp, lpszPrologue);
98       strcat (lpszTemp, ": ");
99       strcat (lpszTemp, lpMsgBuf);
100       ret = JvNewStringLatin1 (lpszTemp);
101     } 
102   else
103     {
104       ret = JvNewStringLatin1 (lpMsgBuf);
105     }
106
107   LocalFree(lpMsgBuf);
108   return ret;
109 }
110
111 jstring
112 _Jv_WinStrError (int nErrorCode)
113 {
114   return _Jv_WinStrError (0, nErrorCode);
115 }
116
117 void _Jv_ThrowIOException (DWORD dwErrorCode)
118 {
119   throw new java::io::IOException (_Jv_WinStrError (dwErrorCode));
120 }
121
122 void _Jv_ThrowIOException()
123 {
124   DWORD dwErrorCode = WSAGetLastError ();
125   _Jv_ThrowIOException (dwErrorCode);
126 }
127
128 void _Jv_ThrowSocketException (DWORD dwErrorCode)
129 {
130   throw new java::net::SocketException (_Jv_WinStrError (dwErrorCode));
131 }
132
133 void _Jv_ThrowSocketException()
134 {
135   DWORD dwErrorCode = WSAGetLastError ();
136   _Jv_ThrowSocketException (dwErrorCode);
137 }
138
139 // Platform-specific VM initialization.
140 void
141 _Jv_platform_initialize (void)
142 {
143   // Initialise winsock for networking
144   WSADATA data;
145   if (WSAStartup (MAKEWORD (1, 1), &data))
146     MessageBox (NULL, "Error initialising winsock library.", "Error",
147     MB_OK | MB_ICONEXCLAMATION);
148
149   // Install exception handler
150   SetUnhandledExceptionFilter (win32_exception_handler);
151
152   // Initialize our executable name
153   GetModuleFileName(NULL, exec_name, sizeof(exec_name));
154 }
155
156 // gettimeofday implementation.
157 jlong
158 _Jv_platform_gettimeofday ()
159 {
160   struct timeb t;
161   ftime (&t);
162   return t.time * 1000LL + t.millitm;
163 }
164
165 // The following definitions "fake out" mingw to think that -mthreads
166 // was enabled and that mingwthr.dll was linked. GCJ-compiled
167 // applications don't need this helper library because we can safely
168 // detect thread death (return from Thread.run()).
169
170 int _CRT_MT = 1;
171
172 extern "C" int
173 __mingwthr_key_dtor (DWORD, void (*) (void *))
174 {
175   // FIXME: for now we do nothing; this causes a memory leak of
176   //        approximately 24 bytes per thread created.
177   return 0;
178 }
179
180 static bool dirExists (const char* dir)
181 {
182   DWORD dwAttrs = ::GetFileAttributes (dir);
183   return dwAttrs != 0xFFFFFFFF &&
184     (dwAttrs & FILE_ATTRIBUTE_DIRECTORY) != 0;
185 }
186
187 static void getUserHome(char* userHome, const char* userId)
188 {
189   char* uh = ::getenv ("USERPROFILE");
190   if (uh)
191     {
192       strcpy(userHome, uh);
193     }
194   else
195     {
196       // Make a half-hearted attempt to support this
197       // legacy version of Windows. Try %WINDIR%\Profiles\%USERNAME%
198       // and failing this, use %WINDIR%.
199       //
200       // See:http://java.sun.com/docs/books/tutorial/security1.2/summary/files.html#UserPolicy
201       //
202       // To do this correctly, we'd have to factor in the
203       // Windows version, but if we did that, then this attempt
204       // wouldn't be half-hearted.
205       char userHomePath[MAX_PATH], winHome[MAX_PATH];
206       ::GetWindowsDirectory(winHome, MAX_PATH);
207         // assume this call always succeeds
208
209       sprintf(userHomePath, "%s\\Profiles\\%s", winHome, userId);
210       if (dirExists (userHomePath))
211         strcpy(userHome, userHomePath);
212       else
213         strcpy(userHome, winHome);
214     }
215 }
216
217 // Set platform-specific System properties.
218 void
219 _Jv_platform_initProperties (java::util::Properties* newprops)
220 {
221   // A convenience define.
222 #define SET(Prop,Val) \
223   newprops->put(JvNewStringLatin1 (Prop), JvNewStringLatin1 (Val))
224
225   SET ("file.separator", "\\");
226   SET ("path.separator", ";");
227   SET ("line.separator", "\r\n");
228
229   // Use GetCurrentDirectory to set 'user.dir'.
230   DWORD buflen = MAX_PATH;
231   char *buffer = (char *) _Jv_MallocUnchecked (buflen);
232   if (buffer != NULL)
233     {
234       if (GetCurrentDirectory (buflen, buffer))
235   SET ("user.dir", buffer);
236
237       if (GetTempPath (buflen, buffer))
238   SET ("java.io.tmpdir", buffer);
239
240       _Jv_Free (buffer);
241     }
242
243   // Use GetUserName to set 'user.name'.
244   buflen = 257;  // UNLEN + 1
245   char userName[buflen];
246   if (GetUserName (userName, &buflen))
247     SET ("user.name", userName);
248
249   // Set user.home
250   char userHome[MAX_PATH];
251   getUserHome(userHome, userName);
252   SET ("user.home", userHome);
253
254   // Get and set some OS info.
255   OSVERSIONINFO osvi;
256   ZeroMemory (&osvi, sizeof(OSVERSIONINFO));
257   osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
258   if (GetVersionEx (&osvi))
259     {
260       char *buffer = (char *) _Jv_MallocUnchecked (30);
261       if (buffer != NULL)
262         {
263           sprintf (buffer, "%d.%d", (int) osvi.dwMajorVersion,
264            (int) osvi.dwMinorVersion);
265           SET ("os.version", buffer);
266           _Jv_Free (buffer);
267         }
268
269       switch (osvi.dwPlatformId)
270         {
271           case VER_PLATFORM_WIN32_WINDOWS:
272             if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
273               SET ("os.name", "Windows 95");
274             else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
275               SET ("os.name", "Windows 98");
276             else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
277               SET ("os.name", "Windows Me");
278             else
279               SET ("os.name", "Windows ??");
280             break;
281
282           case VER_PLATFORM_WIN32_NT:
283             if (osvi.dwMajorVersion <= 4 )
284               SET ("os.name", "Windows NT");
285             else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
286               SET ("os.name", "Windows 2000");
287             else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
288               SET ("os.name", "Windows XP");
289             else
290               SET ("os.name", "Windows NT ??");
291             break;
292
293           default:
294             SET ("os.name", "Windows UNKNOWN");
295             break;
296        }
297   }
298
299   // Set the OS architecture.
300   SYSTEM_INFO si;
301   GetSystemInfo (&si);
302   switch (si.wProcessorArchitecture)
303     {
304       case PROCESSOR_ARCHITECTURE_INTEL:
305         SET ("os.arch", "x86");
306         break;
307       case PROCESSOR_ARCHITECTURE_MIPS:
308         SET ("os.arch", "mips");
309         break;
310       case PROCESSOR_ARCHITECTURE_ALPHA:
311         SET ("os.arch", "alpha");
312         break;
313       case PROCESSOR_ARCHITECTURE_PPC:  
314         SET ("os.arch", "ppc");
315         break;
316       case PROCESSOR_ARCHITECTURE_IA64:
317         SET ("os.arch", "ia64");
318         break;
319       case PROCESSOR_ARCHITECTURE_UNKNOWN:
320       default:
321         SET ("os.arch", "unknown");
322         break;
323     }
324 }
325
326 /* Store up to SIZE return address of the current program state in
327    ARRAY and return the exact number of values stored.  */
328 int
329 backtrace (void **__array, int __size)
330 {
331   register void *_ebp __asm__ ("ebp");
332   register void *_esp __asm__ ("esp");
333   unsigned int *rfp;
334
335   int i=0;
336   for (rfp = *(unsigned int**)_ebp;
337        rfp && i < __size;
338        rfp = *(unsigned int **)rfp)
339     {
340       int diff = *rfp - (unsigned int)rfp;
341       if ((void*)rfp < _esp || diff > 4 * 1024 || diff < 0) break;
342
343     __array[i++] = (void*)(rfp[1]-4);
344   }
345   return i;
346 }
347
348 int
349 _Jv_select (int n, fd_set *readfds, fd_set  *writefds,
350       fd_set *exceptfds, struct timeval *timeout)
351 {
352   int r = ::select (n, readfds, writefds, exceptfds, timeout);
353   if (r == SOCKET_ERROR)
354     {
355       DWORD dwErrorCode = WSAGetLastError ();
356       throw new java::io::IOException (_Jv_WinStrError (dwErrorCode));
357     }
358   return r;      
359 }
360
361 int
362 _Jv_pipe (int filedes[2])
363 {
364   return _pipe (filedes, 4096, _O_BINARY);
365 }
366
367 void
368 _Jv_platform_close_on_exec (HANDLE h)
369 {
370   // Mark the handle as non-inheritable. This has
371   // no effect under Win9X.
372   SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0);
373 }