1 /*
   2  * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
   3  *
   4  * Redistribution and use in source and binary forms, with or without
   5  * modification, are permitted provided that the following conditions
   6  * are met:
   7  *
   8  *   - Redistributions of source code must retain the above copyright
   9  *     notice, this list of conditions and the following disclaimer.
  10  *
  11  *   - Redistributions in binary form must reproduce the above copyright
  12  *     notice, this list of conditions and the following disclaimer in the
  13  *     documentation and/or other materials provided with the distribution.
  14  *
  15  *   - Neither the name of Oracle nor the names of its
  16  *     contributors may be used to endorse or promote products derived
  17  *     from this software without specific prior written permission.
  18  *
  19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30  */
  31 
  32 /*
  33  * This source code is provided to illustrate the usage of a given feature
  34  * or technique and has been deliberately simplified. Additional steps
  35  * required for a production-quality application, such as security checks,
  36  * input validation and proper error handling, might not be present in
  37  * this sample code.
  38  */
  39 
  40 
  41 // To ensure winsock2.h is used, it has to be included ahead of
  42 // windows.h, which includes winsock.h by default.
  43 #include <winsock2.h>
  44 #include <windows.h>
  45 #include <io.h>
  46 #include <sys/types.h>
  47 #include <sys/stat.h>
  48 #include <mmsystem.h>
  49 #include <fcntl.h>
  50 #include <process.h>
  51 
  52 #include "jni.h"
  53 #include "hprof.h"
  54 
  55 int
  56 md_getpid(void)
  57 {
  58     static int pid = -1;
  59 
  60     if ( pid >= 0 ) {
  61         return pid;
  62     }
  63     pid = getpid();
  64     return pid;
  65 }
  66 
  67 void
  68 md_sleep(unsigned seconds)
  69 {
  70     Sleep((DWORD)seconds*1000);
  71 }
  72 
  73 void
  74 md_init(void)
  75 {
  76 }
  77 
  78 int
  79 md_connect(char *hostname, unsigned short port)
  80 {
  81     struct hostent *hentry;
  82     struct sockaddr_in s;
  83     int fd;
  84 
  85     /* create a socket */
  86     fd = (int)socket(AF_INET, SOCK_STREAM, 0);
  87 
  88     /* find remote host's addr from name */
  89     if ((hentry = gethostbyname(hostname)) == NULL) {
  90         return -1;
  91     }
  92     (void)memset((char *)&s, 0, sizeof(s));
  93     /* set remote host's addr; its already in network byte order */
  94     (void)memcpy(&s.sin_addr.s_addr, *(hentry->h_addr_list),
  95            (int)sizeof(s.sin_addr.s_addr));
  96     /* set remote host's port */
  97     s.sin_port = htons(port);
  98     s.sin_family = AF_INET;
  99 
 100     /* now try connecting */
 101     if (-1 == connect(fd, (struct sockaddr*)&s, sizeof(s))) {
 102         return 0;
 103     }
 104     return fd;
 105 }
 106 
 107 int
 108 md_recv(int f, char *buf, int len, int option)
 109 {
 110     return recv(f, buf, len, option);
 111 }
 112 
 113 int
 114 md_shutdown(int filedes, int option)
 115 {
 116     return shutdown(filedes, option);
 117 }
 118 
 119 int
 120 md_open(const char *filename)
 121 {
 122     return open(filename, O_RDONLY);
 123 }
 124 
 125 int
 126 md_open_binary(const char *filename)
 127 {
 128     return open(filename, O_RDONLY|O_BINARY);
 129 }
 130 
 131 int
 132 md_creat(const char *filename)
 133 {
 134     return open(filename, O_CREAT | O_WRONLY | O_TRUNC,
 135                              _S_IREAD | _S_IWRITE);
 136 }
 137 
 138 int
 139 md_creat_binary(const char *filename)
 140 {
 141     return open(filename, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY,
 142                             _S_IREAD | _S_IWRITE);
 143 }
 144 
 145 jlong
 146 md_seek(int filedes, jlong pos)
 147 {
 148     jlong new_pos;
 149 
 150     if ( pos == (jlong)-1 ) {
 151         new_pos = _lseeki64(filedes, 0L, SEEK_END);
 152     } else {
 153         new_pos = _lseeki64(filedes, pos, SEEK_SET);
 154     }
 155     return new_pos;
 156 }
 157 
 158 void
 159 md_close(int filedes)
 160 {
 161     (void)closesocket(filedes);
 162 }
 163 
 164 int
 165 md_send(int s, const char *msg, int len, int flags)
 166 {
 167     return send(s, msg, len, flags);
 168 }
 169 
 170 int
 171 md_read(int filedes, void *buf, int nbyte)
 172 {
 173     return read(filedes, buf, nbyte);
 174 }
 175 
 176 int
 177 md_write(int filedes, const void *buf, int nbyte)
 178 {
 179     return write(filedes, buf, nbyte);
 180 }
 181 
 182 jlong
 183 md_get_microsecs(void)
 184 {
 185     return (jlong)(timeGetTime())*(jlong)1000;
 186 }
 187 
 188 #define FT2JLONG(ft) \
 189         ((jlong)(ft).dwHighDateTime << 32 | (jlong)(ft).dwLowDateTime)
 190 
 191 jlong
 192 md_get_timemillis(void)
 193 {
 194     static jlong fileTime_1_1_70 = 0;
 195     SYSTEMTIME st0;
 196     FILETIME   ft0;
 197 
 198     if (fileTime_1_1_70 == 0) {
 199         /* Initialize fileTime_1_1_70 -- the Win32 file time of midnight
 200          * 1/1/70.
 201          */
 202 
 203         memset(&st0, 0, sizeof(st0));
 204         st0.wYear  = 1970;
 205         st0.wMonth = 1;
 206         st0.wDay   = 1;
 207         SystemTimeToFileTime(&st0, &ft0);
 208         fileTime_1_1_70 = FT2JLONG(ft0);
 209     }
 210 
 211     GetSystemTime(&st0);
 212     SystemTimeToFileTime(&st0, &ft0);
 213 
 214     return (FT2JLONG(ft0) - fileTime_1_1_70) / 10000;
 215 }
 216 
 217 jlong
 218 md_get_thread_cpu_timemillis(void)
 219 {
 220     return md_get_timemillis();
 221 }
 222 
 223 HINSTANCE hJavaInst;
 224 static int nError = 0;
 225 
 226 BOOL WINAPI
 227 DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
 228 {
 229     WSADATA wsaData;
 230     switch (reason) {
 231         case DLL_PROCESS_ATTACH:
 232             hJavaInst = hinst;
 233             nError = WSAStartup(MAKEWORD(2,0), &wsaData);
 234             break;
 235         case DLL_PROCESS_DETACH:
 236             WSACleanup();
 237             hJavaInst = NULL;
 238         default:
 239             break;
 240     }
 241     return TRUE;
 242 }
 243 
 244 void
 245 md_get_prelude_path(char *path, int path_len, char *filename)
 246 {
 247     char libdir[FILENAME_MAX+1];
 248     char *lastSlash;
 249 
 250     GetModuleFileName(hJavaInst, libdir, FILENAME_MAX);
 251 
 252     /* This is actually in the bin directory, so move above bin for lib */
 253     lastSlash = strrchr(libdir, '\\');
 254     if ( lastSlash != NULL ) {
 255         *lastSlash = '\0';
 256     }
 257     lastSlash = strrchr(libdir, '\\');
 258     if ( lastSlash != NULL ) {
 259         *lastSlash = '\0';
 260     }
 261     (void)md_snprintf(path, path_len, "%s\\lib\\%s", libdir, filename);
 262 }
 263 
 264 int
 265 md_vsnprintf(char *s, int n, const char *format, va_list ap)
 266 {
 267     return _vsnprintf(s, n, format, ap);
 268 }
 269 
 270 int
 271 md_snprintf(char *s, int n, const char *format, ...)
 272 {
 273     int ret;
 274     va_list ap;
 275 
 276     va_start(ap, format);
 277     ret = md_vsnprintf(s, n, format, ap);
 278     va_end(ap);
 279     return ret;
 280 }
 281 
 282 void
 283 md_system_error(char *buf, int len)
 284 {
 285     long errval;
 286 
 287     errval = GetLastError();
 288     buf[0] = '\0';
 289     if (errval != 0) {
 290         int n;
 291 
 292         n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
 293                               NULL, errval,
 294                               0, buf, len, NULL);
 295         if (n > 3) {
 296             /* Drop final '.', CR, LF */
 297             if (buf[n - 1] == '\n') n--;
 298             if (buf[n - 1] == '\r') n--;
 299             if (buf[n - 1] == '.') n--;
 300             buf[n] = '\0';
 301         }
 302     }
 303 }
 304 
 305 unsigned
 306 md_htons(unsigned short s)
 307 {
 308     return htons(s);
 309 }
 310 
 311 unsigned
 312 md_htonl(unsigned l)
 313 {
 314     return htonl(l);
 315 }
 316 
 317 unsigned
 318 md_ntohs(unsigned short s)
 319 {
 320     return ntohs(s);
 321 }
 322 
 323 unsigned
 324 md_ntohl(unsigned l)
 325 {
 326     return ntohl(l);
 327 }
 328 
 329 static int
 330 get_last_error_string(char *buf, int len)
 331 {
 332     long errval;
 333 
 334     errval = GetLastError();
 335     if (errval != 0) {
 336         /* DOS error */
 337         int n;
 338 
 339         n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
 340                               NULL, errval,
 341                               0, buf, len, NULL);
 342         if (n > 3) {
 343             /* Drop final '.', CR, LF */
 344             if (buf[n - 1] == '\n') n--;
 345             if (buf[n - 1] == '\r') n--;
 346             if (buf[n - 1] == '.') n--;
 347             buf[n] = '\0';
 348         }
 349         return n;
 350     }
 351 
 352     if (errno != 0) {
 353         /* C runtime error that has no corresponding DOS error code */
 354         const char *s;
 355         int         n;
 356 
 357         s = strerror(errno);
 358         n = (int)strlen(s);
 359         if (n >= len) {
 360             n = len - 1;
 361         }
 362         (void)strncpy(buf, s, n);
 363         buf[n] = '\0';
 364         return n;
 365     }
 366 
 367     return 0;
 368 }
 369 
 370 static void dll_build_name(char* buffer, size_t buflen,
 371                            const char* pname, const char* fname) {
 372     // Loosley based on os_windows.cpp
 373 
 374     char *pathname = (char *)pname;
 375     *buffer = '\0';
 376     while (strlen(pathname) > 0) {
 377         char *p = strchr(pathname, ';');
 378         if (p == NULL) {
 379             p = pathname + strlen(pathname);
 380         }
 381         /* check for NULL path */
 382         if (p == pathname) {
 383             continue;
 384         }
 385         if (*(p-1) == ':' || *(p-1) == '\\') {
 386           (void)_snprintf(buffer, buflen, "%.*s%s.dll", (int)(p - pathname),
 387                             pathname, fname);
 388         } else {
 389           (void)_snprintf(buffer, buflen, "%.*s\\%s.dll", (int)(p - pathname),
 390                             pathname, fname);
 391         }
 392         if (_access(buffer, 0) == 0) {
 393             break;
 394         }
 395         if (*p == '\0') {
 396             pathname = p;
 397         } else {
 398             pathname = p + 1;
 399         }
 400         *buffer = '\0';
 401     }
 402 }
 403 
 404 /* Build a machine dependent library name out of a path and file name.  */
 405 void
 406 md_build_library_name(char *holder, int holderlen, char *pname, char *fname)
 407 {
 408     int   pnamelen;
 409 
 410     pnamelen = pname ? (int)strlen(pname) : 0;
 411 
 412     *holder = '\0';
 413     /* Quietly truncates on buffer overflow. Should be an error. */
 414     if (pnamelen + strlen(fname) + 10 > (unsigned int)holderlen) {
 415         return;
 416     }
 417 
 418     if (pnamelen == 0) {
 419         sprintf(holder, "%s.dll", fname);
 420     } else {
 421       dll_build_name(holder, holderlen, pname, fname);
 422     }
 423 }
 424 
 425 void *
 426 md_load_library(const char * name, char *err_buf, int err_buflen)
 427 {
 428     void *result;
 429 
 430     result = LoadLibrary(name);
 431     if (result == NULL) {
 432         /* Error message is pretty lame, try to make a better guess. */
 433         long errcode;
 434 
 435         errcode = GetLastError();
 436         if (errcode == ERROR_MOD_NOT_FOUND) {
 437             strncpy(err_buf, "Can't find dependent libraries", err_buflen-2);
 438             err_buf[err_buflen-1] = '\0';
 439         } else {
 440             get_last_error_string(err_buf, err_buflen);
 441         }
 442     }
 443     return result;
 444 }
 445 
 446 void
 447 md_unload_library(void *handle)
 448 {
 449     FreeLibrary(handle);
 450 }
 451 
 452 void *
 453 md_find_library_entry(void *handle, const char *name)
 454 {
 455     return GetProcAddress(handle, name);
 456 }