1 /*
   2  * Copyright (c) 2003, 2013, 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     /* find remote host's addr from name */
  86     if ((hentry = gethostbyname(hostname)) == NULL) {
  87         return -1;
  88     }
  89     (void)memset((char *)&s, 0, sizeof(s));
  90     /* set remote host's addr; its already in network byte order */
  91     (void)memcpy(&s.sin_addr.s_addr, *(hentry->h_addr_list),
  92            (int)sizeof(s.sin_addr.s_addr));
  93     /* set remote host's port */
  94     s.sin_port = htons(port);
  95     s.sin_family = AF_INET;
  96 
  97     /* create a socket */
  98     fd = (int)socket(AF_INET, SOCK_STREAM, 0);
  99     if (INVALID_SOCKET == fd) {
 100         return 0;
 101     }
 102 
 103     /* now try connecting */
 104     if (SOCKET_ERROR == connect(fd, (struct sockaddr*)&s, sizeof(s))) {
 105         closesocket(fd);
 106         return 0;
 107     }
 108     return fd;
 109 }
 110 
 111 int
 112 md_recv(int f, char *buf, int len, int option)
 113 {
 114     return recv(f, buf, len, option);
 115 }
 116 
 117 int
 118 md_shutdown(int filedes, int option)
 119 {
 120     return shutdown(filedes, option);
 121 }
 122 
 123 int
 124 md_open(const char *filename)
 125 {
 126     return open(filename, O_RDONLY);
 127 }
 128 
 129 int
 130 md_open_binary(const char *filename)
 131 {
 132     return open(filename, O_RDONLY|O_BINARY);
 133 }
 134 
 135 int
 136 md_creat(const char *filename)
 137 {
 138     return open(filename, O_CREAT | O_WRONLY | O_TRUNC,
 139                              _S_IREAD | _S_IWRITE);
 140 }
 141 
 142 int
 143 md_creat_binary(const char *filename)
 144 {
 145     return open(filename, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY,
 146                             _S_IREAD | _S_IWRITE);
 147 }
 148 
 149 jlong
 150 md_seek(int filedes, jlong pos)
 151 {
 152     jlong new_pos;
 153 
 154     if ( pos == (jlong)-1 ) {
 155         new_pos = _lseeki64(filedes, 0L, SEEK_END);
 156     } else {
 157         new_pos = _lseeki64(filedes, pos, SEEK_SET);
 158     }
 159     return new_pos;
 160 }
 161 
 162 void
 163 md_close(int filedes)
 164 {
 165     (void)closesocket(filedes);
 166 }
 167 
 168 int
 169 md_send(int s, const char *msg, int len, int flags)
 170 {
 171     return send(s, msg, len, flags);
 172 }
 173 
 174 int
 175 md_read(int filedes, void *buf, int nbyte)
 176 {
 177     return read(filedes, buf, nbyte);
 178 }
 179 
 180 int
 181 md_write(int filedes, const void *buf, int nbyte)
 182 {
 183     return write(filedes, buf, nbyte);
 184 }
 185 
 186 jlong
 187 md_get_microsecs(void)
 188 {
 189     return (jlong)(timeGetTime())*(jlong)1000;
 190 }
 191 
 192 #define FT2JLONG(ft) \
 193         ((jlong)(ft).dwHighDateTime << 32 | (jlong)(ft).dwLowDateTime)
 194 
 195 jlong
 196 md_get_timemillis(void)
 197 {
 198     static jlong fileTime_1_1_70 = 0;
 199     SYSTEMTIME st0;
 200     FILETIME   ft0;
 201 
 202     if (fileTime_1_1_70 == 0) {
 203         /* Initialize fileTime_1_1_70 -- the Win32 file time of midnight
 204          * 1/1/70.
 205          */
 206 
 207         memset(&st0, 0, sizeof(st0));
 208         st0.wYear  = 1970;
 209         st0.wMonth = 1;
 210         st0.wDay   = 1;
 211         SystemTimeToFileTime(&st0, &ft0);
 212         fileTime_1_1_70 = FT2JLONG(ft0);
 213     }
 214 
 215     GetSystemTime(&st0);
 216     SystemTimeToFileTime(&st0, &ft0);
 217 
 218     return (FT2JLONG(ft0) - fileTime_1_1_70) / 10000;
 219 }
 220 
 221 jlong
 222 md_get_thread_cpu_timemillis(void)
 223 {
 224     return md_get_timemillis();
 225 }
 226 
 227 HINSTANCE hJavaInst;
 228 static int nError = 0;
 229 
 230 BOOL WINAPI
 231 DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
 232 {
 233     WSADATA wsaData;
 234     switch (reason) {
 235         case DLL_PROCESS_ATTACH:
 236             hJavaInst = hinst;
 237             nError = WSAStartup(MAKEWORD(2,0), &wsaData);
 238             break;
 239         case DLL_PROCESS_DETACH:
 240             WSACleanup();
 241             hJavaInst = NULL;
 242         default:
 243             break;
 244     }
 245     return TRUE;
 246 }
 247 
 248 void
 249 md_get_prelude_path(char *path, int path_len, char *filename)
 250 {
 251     char libdir[FILENAME_MAX+1];
 252     char *lastSlash;
 253 
 254     GetModuleFileName(hJavaInst, libdir, FILENAME_MAX);
 255 
 256     /* This is actually in the bin directory, so move above bin for lib */
 257     lastSlash = strrchr(libdir, '\\');
 258     if ( lastSlash != NULL ) {
 259         *lastSlash = '\0';
 260     }
 261     lastSlash = strrchr(libdir, '\\');
 262     if ( lastSlash != NULL ) {
 263         *lastSlash = '\0';
 264     }
 265     (void)md_snprintf(path, path_len, "%s\\lib\\%s", libdir, filename);
 266 }
 267 
 268 int
 269 md_vsnprintf(char *s, int n, const char *format, va_list ap)
 270 {
 271     return _vsnprintf(s, n, format, ap);
 272 }
 273 
 274 int
 275 md_snprintf(char *s, int n, const char *format, ...)
 276 {
 277     int ret;
 278     va_list ap;
 279 
 280     va_start(ap, format);
 281     ret = md_vsnprintf(s, n, format, ap);
 282     va_end(ap);
 283     return ret;
 284 }
 285 
 286 void
 287 md_system_error(char *buf, int len)
 288 {
 289     long errval;
 290 
 291     errval = GetLastError();
 292     buf[0] = '\0';
 293     if (errval != 0) {
 294         int n;
 295 
 296         n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
 297                               NULL, errval,
 298                               0, buf, len, NULL);
 299         if (n > 3) {
 300             /* Drop final '.', CR, LF */
 301             if (buf[n - 1] == '\n') n--;
 302             if (buf[n - 1] == '\r') n--;
 303             if (buf[n - 1] == '.') n--;
 304             buf[n] = '\0';
 305         }
 306     }
 307 }
 308 
 309 unsigned
 310 md_htons(unsigned short s)
 311 {
 312     return htons(s);
 313 }
 314 
 315 unsigned
 316 md_htonl(unsigned l)
 317 {
 318     return htonl(l);
 319 }
 320 
 321 unsigned
 322 md_ntohs(unsigned short s)
 323 {
 324     return ntohs(s);
 325 }
 326 
 327 unsigned
 328 md_ntohl(unsigned l)
 329 {
 330     return ntohl(l);
 331 }
 332 
 333 static int
 334 get_last_error_string(char *buf, int len)
 335 {
 336     long errval;
 337 
 338     errval = GetLastError();
 339     if (errval != 0) {
 340         /* DOS error */
 341         int n;
 342 
 343         n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
 344                               NULL, errval,
 345                               0, buf, len, NULL);
 346         if (n > 3) {
 347             /* Drop final '.', CR, LF */
 348             if (buf[n - 1] == '\n') n--;
 349             if (buf[n - 1] == '\r') n--;
 350             if (buf[n - 1] == '.') n--;
 351             buf[n] = '\0';
 352         }
 353         return n;
 354     }
 355 
 356     if (errno != 0) {
 357         /* C runtime error that has no corresponding DOS error code */
 358         const char *s;
 359         int         n;
 360 
 361         s = strerror(errno);
 362         n = (int)strlen(s);
 363         if (n >= len) {
 364             n = len - 1;
 365         }
 366         (void)strncpy(buf, s, n);
 367         buf[n] = '\0';
 368         return n;
 369     }
 370 
 371     return 0;
 372 }
 373 
 374 static void dll_build_name(char* buffer, size_t buflen,
 375                            const char* paths, const char* fname) {
 376     char *path, *paths_copy, *next_token;
 377 
 378     paths_copy = strdup(paths);
 379     if (paths_copy == NULL) {
 380         return;
 381     }
 382 
 383     next_token = NULL;
 384     path = strtok_s(paths_copy, ";", &next_token);
 385 
 386     while (path != NULL) {
 387         _snprintf(buffer, buflen, "%s\\%s.dll", path, fname);
 388         if (_access(buffer, 0) == 0) {
 389             break;
 390         }
 391         *buffer = '\0';
 392         path = strtok_s(NULL, ";", &next_token);
 393     }
 394 
 395     free(paths_copy);
 396 }
 397 
 398 /* Build a machine dependent library name out of a path and file name.  */
 399 void
 400 md_build_library_name(char *holder, int holderlen, const char *pname, const char *fname)
 401 {
 402     int   pnamelen;
 403 
 404     pnamelen = pname ? (int)strlen(pname) : 0;
 405 
 406     *holder = '\0';
 407     /* Quietly truncates on buffer overflow. Should be an error. */
 408     if (pnamelen + strlen(fname) + 10 > (unsigned int)holderlen) {
 409         return;
 410     }
 411 
 412     if (pnamelen == 0) {
 413         sprintf(holder, "%s.dll", fname);
 414     } else {
 415       dll_build_name(holder, holderlen, pname, fname);
 416     }
 417 }
 418 
 419 void *
 420 md_load_library(const char * name, char *err_buf, int err_buflen)
 421 {
 422     void *result;
 423 
 424     result = LoadLibrary(name);
 425     if (result == NULL) {
 426         /* Error message is pretty lame, try to make a better guess. */
 427         long errcode;
 428 
 429         errcode = GetLastError();
 430         if (errcode == ERROR_MOD_NOT_FOUND) {
 431             strncpy(err_buf, "Can't find dependent libraries", err_buflen-2);
 432             err_buf[err_buflen-1] = '\0';
 433         } else {
 434             get_last_error_string(err_buf, err_buflen);
 435         }
 436     }
 437     return result;
 438 }
 439 
 440 void
 441 md_unload_library(void *handle)
 442 {
 443     FreeLibrary(handle);
 444 }
 445 
 446 void *
 447 md_find_library_entry(void *handle, const char *name)
 448 {
 449     return GetProcAddress(handle, name);
 450 }