< prev index next >

src/java.base/windows/native/libjava/TimeZone_md.c

Print this page
rev 51713 : [mq]: 8209167


  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <windows.h>
  27 #include <stdio.h>
  28 #include <stdlib.h>
  29 #include "jvm.h"
  30 #include "TimeZone_md.h"
  31 
  32 #define VALUE_UNKNOWN           0
  33 #define VALUE_KEY               1
  34 #define VALUE_MAPID             2
  35 #define VALUE_GMTOFFSET         3
  36 
  37 #define MAX_ZONE_CHAR           256
  38 #define MAX_MAPID_LENGTH        32

  39 
  40 #define NT_TZ_KEY               "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"
  41 #define WIN_TZ_KEY              "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Time Zones"
  42 #define WIN_CURRENT_TZ_KEY      "System\\CurrentControlSet\\Control\\TimeZoneInformation"
  43 
  44 typedef struct _TziValue {
  45     LONG        bias;
  46     LONG        stdBias;
  47     LONG        dstBias;
  48     SYSTEMTIME  stdDate;
  49     SYSTEMTIME  dstDate;
  50 } TziValue;
  51 
  52 /*
  53  * Registry key names
  54  */
  55 static void *keyNames[] = {
  56     (void *) L"StandardName",
  57     (void *) "StandardName",
  58     (void *) L"Std",


 128     if (bias > 0) {
 129         gmtOffset = bias;
 130         sign = -1;
 131     } else {
 132         gmtOffset = -bias;
 133         sign = 1;
 134     }
 135     if (gmtOffset != 0) {
 136         sprintf(buffer, "GMT%c%02d:%02d",
 137                 ((sign >= 0) ? '+' : '-'),
 138                 gmtOffset / 60,
 139                 gmtOffset % 60);
 140     } else {
 141         strcpy(buffer, "GMT");
 142     }
 143 }
 144 
 145 /*
 146  * Gets the current time zone entry in the "Time Zones" registry.
 147  */
 148 static int getWinTimeZone(char *winZoneName, char *winMapID)
 149 {
 150     DYNAMIC_TIME_ZONE_INFORMATION dtzi;
 151     DWORD timeType;
 152     DWORD bufSize;
 153     DWORD val;
 154     HANDLE hKey = NULL;
 155     LONG ret;
 156     ULONG valueType;
 157 
 158     /*
 159      * Get the dynamic time zone information so that time zone redirection
 160      * can be supported. (see JDK-7044727)
 161      */
 162     timeType = GetDynamicTimeZoneInformation(&dtzi);
 163     if (timeType == TIME_ZONE_ID_INVALID) {
 164         goto err;
 165     }
 166 
 167     /*
 168      * Make sure TimeZoneKeyName is available from the API call. If


 214         ret = RegQueryValueExA(hKey, "TimeZoneKeyName", NULL,
 215                                &valueType, (LPBYTE) winZoneName, &bufSize);
 216         if (ret != ERROR_SUCCESS) {
 217             goto err;
 218         }
 219         (void) RegCloseKey(hKey);
 220         return VALUE_KEY;
 221     } else {
 222         /*
 223          * Fall back to GetTimeZoneInformation
 224          */
 225         TIME_ZONE_INFORMATION tzi;
 226         HANDLE hSubKey = NULL;
 227         DWORD nSubKeys, i;
 228         ULONG valueType;
 229         TCHAR subKeyName[MAX_ZONE_CHAR];
 230         TCHAR szValue[MAX_ZONE_CHAR];
 231         WCHAR stdNameInReg[MAX_ZONE_CHAR];
 232         TziValue tempTzi;
 233         WCHAR *stdNamePtr = tzi.StandardName;
 234         DWORD valueSize;
 235         int onlyMapID;
 236 
 237         timeType = GetTimeZoneInformation(&tzi);
 238         if (timeType == TIME_ZONE_ID_INVALID) {
 239             goto err;
 240         }
 241 
 242         ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_CURRENT_TZ_KEY, 0,
 243                            KEY_READ, (PHKEY)&hKey);
 244         if (ret == ERROR_SUCCESS) {
 245             /*
 246              * Determine if auto-daylight time adjustment is turned off.
 247              */
 248             bufSize = sizeof(val);
 249             ret = RegQueryValueExA(hKey, "DynamicDaylightTimeDisabled", NULL,
 250                                    &valueType, (LPBYTE) &val, &bufSize);
 251             if (ret == ERROR_SUCCESS) {
 252                 if (val == 1 && tzi.DaylightDate.wMonth != 0) {
 253                     (void) RegCloseKey(hKey);
 254                     customZoneName(tzi.Bias, winZoneName);


 355                     if (tzi.DaylightBias != 0) {
 356                         if ((tzi.DaylightBias != tempTzi.dstBias) ||
 357                             (memcmp((const void *) &tzi.DaylightDate,
 358                                     (const void *) &tempTzi.dstDate,
 359                                     sizeof(SYSTEMTIME)) != 0)) {
 360                             goto out;
 361                         }
 362                     }
 363                 }
 364 
 365                 /*
 366                  * found matched record, terminate search
 367                  */
 368                 strcpy(winZoneName, subKeyName);
 369                 break;
 370             }
 371         out:
 372             (void) RegCloseKey(hSubKey);
 373         }
 374 
 375         /*
 376          * Get the "MapID" value of the registry to be able to eliminate
 377          * duplicated key names later.
 378          */
 379         valueSize = MAX_MAPID_LENGTH;
 380         ret = RegQueryValueExA(hSubKey, "MapID", NULL, &valueType, winMapID, &valueSize);
 381         (void) RegCloseKey(hSubKey);
 382         (void) RegCloseKey(hKey);
 383 
 384         if (ret != ERROR_SUCCESS) {
 385             /*
 386              * Vista doesn't have mapID. VALUE_UNKNOWN should be returned
 387              * only for Windows NT.
 388              */
 389             if (onlyMapID == 1) {
 390                 return VALUE_UNKNOWN;
 391             }
 392         }
 393     }
 394 
 395     return VALUE_KEY;
 396 
 397  err:
 398     if (hKey != NULL) {
 399         (void) RegCloseKey(hKey);
 400     }
 401     return VALUE_UNKNOWN;
 402 }
 403 
 404 /*
 405  * The mapping table file name.
 406  */
 407 #define MAPPINGS_FILE "\\lib\\tzmappings"
 408 
 409 /*
 410  * Index values for the mapping table.
 411  */
 412 #define TZ_WIN_NAME     0
 413 #define TZ_MAPID        1
 414 #define TZ_REGION       2
 415 #define TZ_JAVA_NAME    3
 416 
 417 #define TZ_NITEMS       4       /* number of items (fields) */
 418 
 419 /*
 420  * Looks up the mapping table (tzmappings) and returns a Java time
 421  * zone ID (e.g., "America/Los_Angeles") if found. Otherwise, NULL is
 422  * returned.
 423  *
 424  * value_type is one of the following values:
 425  *      VALUE_KEY for exact key matching
 426  *      VALUE_MAPID for MapID (this is
 427  *      required for the old Windows, such as NT 4.0 SP3).
 428  */
 429 static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName,
 430                          char *mapID)
 431 {
 432     int line;
 433     int IDmatched = 0;
 434     FILE *fp;
 435     char *javaTZName = NULL;
 436     char *items[TZ_NITEMS];
 437     char *mapFileName;
 438     char lineBuffer[MAX_ZONE_CHAR * 4];
 439     int noMapID = *mapID == '\0';       /* no mapID on Vista and later */
 440     int offset = 0;
 441     const char* errorMessage = "unknown error";














 442 
 443     mapFileName = malloc(strlen(java_home_dir) + strlen(MAPPINGS_FILE) + 1);
 444     if (mapFileName == NULL) {
 445         return NULL;
 446     }
 447     strcpy(mapFileName, java_home_dir);
 448     strcat(mapFileName, MAPPINGS_FILE);
 449 
 450     if ((fp = fopen(mapFileName, "r")) == NULL) {
 451         jio_fprintf(stderr, "can't open %s.\n", mapFileName);
 452         free((void *) mapFileName);
 453         return NULL;
 454     }
 455     free((void *) mapFileName);
 456 
 457     line = 0;
 458     while (fgets(lineBuffer, sizeof(lineBuffer), fp) != NULL) {
 459         char *start, *idx, *endp;
 460         int itemIndex = 0;
 461 


 477                     errorMessage = "premature end of line";
 478                     offset = (int)(idx - lineBuffer);
 479                     goto illegal_format;
 480                 }
 481             }
 482             if (*idx == '\0') {
 483                 errorMessage = "illegal null character found";
 484                 offset = (int)(idx - lineBuffer);
 485                 goto illegal_format;
 486             }
 487             *idx++ = '\0';
 488             start = idx;
 489         }
 490 
 491         if (*idx != '\n') {
 492             errorMessage = "illegal non-newline character found";
 493             offset = (int)(idx - lineBuffer);
 494             goto illegal_format;
 495         }
 496 
 497         if (noMapID || strcmp(mapID, items[TZ_MAPID]) == 0) {
 498             /*
 499              * When there's no mapID, we need to scan items until the
 500              * exact match is found or the end of data is detected.
 501              */
 502             if (!noMapID) {
 503                 IDmatched = 1;
 504             }
 505             if (strcmp(items[TZ_WIN_NAME], tzName) == 0) {
 506                 /*
 507                  * Found the time zone in the mapping table.

 508                  */


 509                 javaTZName = _strdup(items[TZ_JAVA_NAME]);
 510                 break;
 511             }
 512         } else {
 513             if (IDmatched == 1) {
 514                 /*
 515                  * No need to look up the mapping table further.
 516                  */
 517                 break;
 518             }
 519         }
 520     }
 521     fclose(fp);
 522 
 523     return javaTZName;
 524 
 525  illegal_format:
 526     (void) fclose(fp);
 527     jio_fprintf(stderr, "Illegal format in tzmappings file: %s at line %d, offset %d.\n",
 528                 errorMessage, line, offset);
 529     return NULL;
 530 }
 531 
 532 /*
 533  * Detects the platform time zone which maps to a Java time zone ID.
 534  */
 535 char *findJavaTZ_md(const char *java_home_dir)
 536 {
 537     char winZoneName[MAX_ZONE_CHAR];
 538     char winMapID[MAX_MAPID_LENGTH];
 539     char *std_timezone = NULL;
 540     int  result;
 541 
 542     winMapID[0] = 0;
 543     result = getWinTimeZone(winZoneName, winMapID);
 544 
 545     if (result != VALUE_UNKNOWN) {
 546         if (result == VALUE_GMTOFFSET) {
 547             std_timezone = _strdup(winZoneName);
 548         } else {
 549             std_timezone = matchJavaTZ(java_home_dir, result,
 550                                        winZoneName, winMapID);
 551             if (std_timezone == NULL) {
 552                 std_timezone = getGMTOffsetID();
 553             }
 554         }
 555     }
 556     return std_timezone;
 557 }
 558 
 559 /**
 560  * Returns a GMT-offset-based time zone ID.
 561  */
 562 char *
 563 getGMTOffsetID()
 564 {
 565     LONG bias = 0;
 566     LONG ret;
 567     HANDLE hKey = NULL;
 568     char zonename[32];
 569 
 570     // Obtain the current GMT offset value of ActiveTimeBias.




  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <windows.h>
  27 #include <stdio.h>
  28 #include <stdlib.h>
  29 #include "jvm.h"
  30 #include "TimeZone_md.h"
  31 
  32 #define VALUE_UNKNOWN           0
  33 #define VALUE_KEY               1
  34 #define VALUE_MAPID             2
  35 #define VALUE_GMTOFFSET         3
  36 
  37 #define MAX_ZONE_CHAR           256
  38 #define MAX_MAPID_LENGTH        32
  39 #define MAX_REGION_LENGTH       4
  40 
  41 #define NT_TZ_KEY               "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"
  42 #define WIN_TZ_KEY              "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Time Zones"
  43 #define WIN_CURRENT_TZ_KEY      "System\\CurrentControlSet\\Control\\TimeZoneInformation"
  44 
  45 typedef struct _TziValue {
  46     LONG        bias;
  47     LONG        stdBias;
  48     LONG        dstBias;
  49     SYSTEMTIME  stdDate;
  50     SYSTEMTIME  dstDate;
  51 } TziValue;
  52 
  53 /*
  54  * Registry key names
  55  */
  56 static void *keyNames[] = {
  57     (void *) L"StandardName",
  58     (void *) "StandardName",
  59     (void *) L"Std",


 129     if (bias > 0) {
 130         gmtOffset = bias;
 131         sign = -1;
 132     } else {
 133         gmtOffset = -bias;
 134         sign = 1;
 135     }
 136     if (gmtOffset != 0) {
 137         sprintf(buffer, "GMT%c%02d:%02d",
 138                 ((sign >= 0) ? '+' : '-'),
 139                 gmtOffset / 60,
 140                 gmtOffset % 60);
 141     } else {
 142         strcpy(buffer, "GMT");
 143     }
 144 }
 145 
 146 /*
 147  * Gets the current time zone entry in the "Time Zones" registry.
 148  */
 149 static int getWinTimeZone(char *winZoneName)
 150 {
 151     DYNAMIC_TIME_ZONE_INFORMATION dtzi;
 152     DWORD timeType;
 153     DWORD bufSize;
 154     DWORD val;
 155     HANDLE hKey = NULL;
 156     LONG ret;
 157     ULONG valueType;
 158 
 159     /*
 160      * Get the dynamic time zone information so that time zone redirection
 161      * can be supported. (see JDK-7044727)
 162      */
 163     timeType = GetDynamicTimeZoneInformation(&dtzi);
 164     if (timeType == TIME_ZONE_ID_INVALID) {
 165         goto err;
 166     }
 167 
 168     /*
 169      * Make sure TimeZoneKeyName is available from the API call. If


 215         ret = RegQueryValueExA(hKey, "TimeZoneKeyName", NULL,
 216                                &valueType, (LPBYTE) winZoneName, &bufSize);
 217         if (ret != ERROR_SUCCESS) {
 218             goto err;
 219         }
 220         (void) RegCloseKey(hKey);
 221         return VALUE_KEY;
 222     } else {
 223         /*
 224          * Fall back to GetTimeZoneInformation
 225          */
 226         TIME_ZONE_INFORMATION tzi;
 227         HANDLE hSubKey = NULL;
 228         DWORD nSubKeys, i;
 229         ULONG valueType;
 230         TCHAR subKeyName[MAX_ZONE_CHAR];
 231         TCHAR szValue[MAX_ZONE_CHAR];
 232         WCHAR stdNameInReg[MAX_ZONE_CHAR];
 233         TziValue tempTzi;
 234         WCHAR *stdNamePtr = tzi.StandardName;

 235         int onlyMapID;
 236 
 237         timeType = GetTimeZoneInformation(&tzi);
 238         if (timeType == TIME_ZONE_ID_INVALID) {
 239             goto err;
 240         }
 241 
 242         ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_CURRENT_TZ_KEY, 0,
 243                            KEY_READ, (PHKEY)&hKey);
 244         if (ret == ERROR_SUCCESS) {
 245             /*
 246              * Determine if auto-daylight time adjustment is turned off.
 247              */
 248             bufSize = sizeof(val);
 249             ret = RegQueryValueExA(hKey, "DynamicDaylightTimeDisabled", NULL,
 250                                    &valueType, (LPBYTE) &val, &bufSize);
 251             if (ret == ERROR_SUCCESS) {
 252                 if (val == 1 && tzi.DaylightDate.wMonth != 0) {
 253                     (void) RegCloseKey(hKey);
 254                     customZoneName(tzi.Bias, winZoneName);


 355                     if (tzi.DaylightBias != 0) {
 356                         if ((tzi.DaylightBias != tempTzi.dstBias) ||
 357                             (memcmp((const void *) &tzi.DaylightDate,
 358                                     (const void *) &tempTzi.dstDate,
 359                                     sizeof(SYSTEMTIME)) != 0)) {
 360                             goto out;
 361                         }
 362                     }
 363                 }
 364 
 365                 /*
 366                  * found matched record, terminate search
 367                  */
 368                 strcpy(winZoneName, subKeyName);
 369                 break;
 370             }
 371         out:
 372             (void) RegCloseKey(hSubKey);
 373         }
 374 







 375         (void) RegCloseKey(hKey);










 376     }
 377 
 378     return VALUE_KEY;
 379 
 380  err:
 381     if (hKey != NULL) {
 382         (void) RegCloseKey(hKey);
 383     }
 384     return VALUE_UNKNOWN;
 385 }
 386 
 387 /*
 388  * The mapping table file name.
 389  */
 390 #define MAPPINGS_FILE "\\lib\\tzmappings"
 391 
 392 /*
 393  * Index values for the mapping table.
 394  */
 395 #define TZ_WIN_NAME     0
 396 #define TZ_REGION       1
 397 #define TZ_JAVA_NAME    2

 398 
 399 #define TZ_NITEMS       3       /* number of items (fields) */
 400 
 401 /*
 402  * Looks up the mapping table (tzmappings) and returns a Java time
 403  * zone ID (e.g., "America/Los_Angeles") if found. Otherwise, NULL is
 404  * returned.





 405  */
 406 static char *matchJavaTZ(const char *java_home_dir, char *tzName)

 407 {
 408     int line;
 409     int IDmatched = 0;
 410     FILE *fp;
 411     char *javaTZName = NULL;
 412     char *items[TZ_NITEMS];
 413     char *mapFileName;
 414     char lineBuffer[MAX_ZONE_CHAR * 4];

 415     int offset = 0;
 416     const char* errorMessage = "unknown error";
 417     char region[MAX_REGION_LENGTH];
 418 
 419     // Get the user's location
 420     if (GetGeoInfo(GetUserGeoID(GEOCLASS_NATION),
 421             GEO_ISO2, region, MAX_REGION_LENGTH, 0) == 0) {
 422         // If GetGeoInfo fails, fallback to LCID's country
 423         LCID lcid = GetUserDefaultLCID();
 424         if (GetLocaleInfo(lcid,
 425                           LOCALE_SISO3166CTRYNAME, region, MAX_REGION_LENGTH) == 0 &&
 426             GetLocaleInfo(lcid,
 427                           LOCALE_SISO3166CTRYNAME2, region, MAX_REGION_LENGTH) == 0) {
 428             region[0] = '\0';
 429         }
 430     }
 431 
 432     mapFileName = malloc(strlen(java_home_dir) + strlen(MAPPINGS_FILE) + 1);
 433     if (mapFileName == NULL) {
 434         return NULL;
 435     }
 436     strcpy(mapFileName, java_home_dir);
 437     strcat(mapFileName, MAPPINGS_FILE);
 438 
 439     if ((fp = fopen(mapFileName, "r")) == NULL) {
 440         jio_fprintf(stderr, "can't open %s.\n", mapFileName);
 441         free((void *) mapFileName);
 442         return NULL;
 443     }
 444     free((void *) mapFileName);
 445 
 446     line = 0;
 447     while (fgets(lineBuffer, sizeof(lineBuffer), fp) != NULL) {
 448         char *start, *idx, *endp;
 449         int itemIndex = 0;
 450 


 466                     errorMessage = "premature end of line";
 467                     offset = (int)(idx - lineBuffer);
 468                     goto illegal_format;
 469                 }
 470             }
 471             if (*idx == '\0') {
 472                 errorMessage = "illegal null character found";
 473                 offset = (int)(idx - lineBuffer);
 474                 goto illegal_format;
 475             }
 476             *idx++ = '\0';
 477             start = idx;
 478         }
 479 
 480         if (*idx != '\n') {
 481             errorMessage = "illegal non-newline character found";
 482             offset = (int)(idx - lineBuffer);
 483             goto illegal_format;
 484         }
 485 

 486         /*
 487          * We need to scan items until the
 488          * exact match is found or the end of data is detected.
 489          */



 490         if (strcmp(items[TZ_WIN_NAME], tzName) == 0) {
 491             /*
 492              * Found the time zone in the mapping table.
 493              * Check the region code and select the appropriate entry
 494              */
 495             if (strcmp(items[TZ_REGION], region) == 0 ||
 496                 strcmp(items[TZ_REGION], "001") == 0) {
 497                 javaTZName = _strdup(items[TZ_JAVA_NAME]);
 498                 break;
 499             }







 500         }
 501     }
 502     fclose(fp);
 503 
 504     return javaTZName;
 505 
 506  illegal_format:
 507     (void) fclose(fp);
 508     jio_fprintf(stderr, "Illegal format in tzmappings file: %s at line %d, offset %d.\n",
 509                 errorMessage, line, offset);
 510     return NULL;
 511 }
 512 
 513 /*
 514  * Detects the platform time zone which maps to a Java time zone ID.
 515  */
 516 char *findJavaTZ_md(const char *java_home_dir)
 517 {
 518     char winZoneName[MAX_ZONE_CHAR];

 519     char *std_timezone = NULL;
 520     int  result;
 521 
 522     result = getWinTimeZone(winZoneName);

 523 
 524     if (result != VALUE_UNKNOWN) {
 525         if (result == VALUE_GMTOFFSET) {
 526             std_timezone = _strdup(winZoneName);
 527         } else {
 528             std_timezone = matchJavaTZ(java_home_dir, winZoneName);

 529             if (std_timezone == NULL) {
 530                 std_timezone = getGMTOffsetID();
 531             }
 532         }
 533     }
 534     return std_timezone;
 535 }
 536 
 537 /**
 538  * Returns a GMT-offset-based time zone ID.
 539  */
 540 char *
 541 getGMTOffsetID()
 542 {
 543     LONG bias = 0;
 544     LONG ret;
 545     HANDLE hKey = NULL;
 546     char zonename[32];
 547 
 548     // Obtain the current GMT offset value of ActiveTimeBias.


< prev index next >