ICU-9752 Update Windows time zone detection to use CLDR data

X-SVN-Rev: 32860
diff --git a/source/common/wintz.c b/source/common/wintz.c
index f64a4ad..c9bb15a 100644
--- a/source/common/wintz.c
+++ b/source/common/wintz.c
@@ -1,6 +1,6 @@
 /*
 ********************************************************************************
-*   Copyright (C) 2005-2007, International Business Machines
+*   Copyright (C) 2005-2012, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 ********************************************************************************
 *
@@ -14,11 +14,11 @@
 #ifdef U_WINDOWS
 
 #include "wintz.h"
-
 #include "cmemory.h"
 #include "cstring.h"
 
 #include "unicode/ustring.h"
+#include "unicode/ures.h"
 
 #   define WIN32_LEAN_AND_MEAN
 #   define VC_EXTRALEAN
@@ -28,11 +28,7 @@
 #   define NOMCX
 #include <windows.h>
 
-#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
-#define NEW_ARRAY(type,count) (type *) uprv_malloc((count) * sizeof(type))
-#define DELETE_ARRAY(array) uprv_free((void *) (array))
-
-#define ICUID_STACK_BUFFER_SIZE 32
+#define MAX_LENGTH_ID 40
 
 /* The layout of the Tzi value in the registry */
 typedef struct
@@ -44,17 +40,6 @@
     SYSTEMTIME daylightDate;
 } TZI;
 
-typedef struct
-{
-    const char *icuid;
-    const char *winid;
-} WindowsICUMap;
-
-typedef struct {
-    const char* winid;
-    const char* altwinid;
-} WindowsZoneRemap;
-
 /**
  * Various registry keys and key fragments.
  */
@@ -98,252 +83,12 @@
  * the registry.
  */
 enum {
-    WIN_9X_ME_TYPE = 0,
-    WIN_NT_TYPE = 1,
-    WIN_2K_XP_TYPE = 2
+    WIN_9X_ME_TYPE = 1,
+    WIN_NT_TYPE = 2,
+    WIN_2K_XP_TYPE = 3
 };
 
-# if 0
-/*
- * ZONE_MAP from supplementalData.txt
- */
-static const WindowsICUMap NEW_ZONE_MAP[] = {
-    {"Africa/Cairo",         "Egypt"},
-    {"Africa/Casablanca",    "Greenwich"},
-    {"Africa/Johannesburg",  "South Africa"},
-    {"Africa/Lagos",         "W. Central Africa"},
-    {"Africa/Nairobi",       "E. Africa"},
-    {"Africa/Windhoek",      "Namibia"},
-    {"America/Anchorage",    "Alaskan"},
-    {"America/Bogota",       "SA Pacific"},
-    {"America/Buenos_Aires", "SA Eastern"},
-    {"America/Caracas",      "SA Western"},
-    {"America/Chicago",      "Central"},
-    {"America/Chihuahua",    "Mountain Standard Time (Mexico)"},
-    {"America/Denver",       "Mountain"},
-    {"America/Godthab",      "Greenland"},
-    {"America/Guatemala",    "Central America"},
-    {"America/Halifax",      "Atlantic"},
-    {"America/Indianapolis", "US Eastern"},
-    {"America/Los_Angeles",  "Pacific"},
-    {"America/Manaus",       "Central Brazilian"},
-    {"America/Mexico_City",  "Central Standard Time (Mexico)"},
-    {"America/Montevideo",   "Montevideo"},
-    {"America/New_York",     "Eastern"},
-    {"America/Noronha",      "Mid-Atlantic"},
-    {"America/Phoenix",      "US Mountain"},
-    {"America/Regina",       "Canada Central"},
-    {"America/Santiago",     "Pacific SA"},
-    {"America/Sao_Paulo",    "E. South America"},
-    {"America/St_Johns",     "Newfoundland"},
-    {"America/Tijuana",      "Pacific Standard Time (Mexico)"},
-    {"Asia/Amman",           "Jordan"},
-    {"Asia/Baghdad",         "Arabic"},
-    {"Asia/Baku",            "Azerbaijan"},
-    {"Asia/Bangkok",         "SE Asia"},
-    {"Asia/Beirut",          "Middle East"},
-    {"Asia/Calcutta",        "India"},
-    {"Asia/Colombo",         "Sri Lanka"},
-    {"Asia/Dhaka",           "Central Asia"},
-    {"Asia/Jerusalem",       "Israel"},
-    {"Asia/Kabul",           "Afghanistan"},
-    {"Asia/Karachi",         "West Asia"},
-    {"Asia/Katmandu",        "Nepal"},
-    {"Asia/Krasnoyarsk",     "North Asia"},
-    {"Asia/Muscat",          "Arabian"},
-    {"Asia/Novosibirsk",     "N. Central Asia"},
-    {"Asia/Rangoon",         "Myanmar"},
-    {"Asia/Riyadh",          "Arab"},
-    {"Asia/Seoul",           "Korea"},
-    {"Asia/Shanghai",        "China"},
-    {"Asia/Singapore",       "Singapore"},
-    {"Asia/Taipei",          "Taipei"},
-    {"Asia/Tbilisi",         "Georgian"},
-    {"Asia/Tehran",          "Iran"},
-    {"Asia/Tokyo",           "Tokyo"},
-    {"Asia/Ulaanbaatar",     "North Asia East"},
-    {"Asia/Vladivostok",     "Vladivostok"},
-    {"Asia/Yakutsk",         "Yakutsk"},
-    {"Asia/Yekaterinburg",   "Ekaterinburg"},
-    {"Asia/Yerevan",         "Caucasus"},
-    {"Atlantic/Azores",      "Azores"},
-    {"Atlantic/Cape_Verde",  "Cape Verde"},
-    {"Australia/Adelaide",   "Cen. Australia"},
-    {"Australia/Brisbane",   "E. Australia"},
-    {"Australia/Darwin",     "AUS Central"},
-    {"Australia/Hobart",     "Tasmania"},
-    {"Australia/Perth",      "W. Australia"},
-    {"Australia/Sydney",     "AUS Eastern"},
-    {"Europe/Berlin",        "W. Europe"},
-    {"Europe/Helsinki",      "FLE"},
-    {"Europe/Istanbul",      "GTB"},
-    {"Europe/London",        "GMT"},
-    {"Europe/Minsk",         "E. Europe"},
-    {"Europe/Moscow",        "Russian"},
-    {"Europe/Paris",         "Romance"},
-    {"Europe/Prague",        "Central Europe"},
-    {"Europe/Warsaw",        "Central European"},
-    {"Pacific/Apia",         "Samoa"},
-    {"Pacific/Auckland",     "New Zealand"},
-    {"Pacific/Fiji",         "Fiji"},
-    {"Pacific/Guadalcanal",  "Central Pacific"},
-    {"Pacific/Guam",         "West Pacific"},
-    {"Pacific/Honolulu",     "Hawaiian"},
-    {"Pacific/Kwajalein",    "Dateline"},
-    {"Pacific/Tongatapu",    "Tonga"}
-};
-#endif
-
-/* NOTE: Some Windows zone ids appear more than once. In such cases the
- * ICU zone id from the first one is the preferred match.
- */
-static const WindowsICUMap ZONE_MAP[] = {
-    {"Pacific/Kwajalein",    "Dateline"}, /* S (GMT-12:00) International Date Line West */
-    {"Etc/GMT+12",           "Dateline"}, /* S (GMT-12:00) International Date Line West */
-
-    {"Pacific/Apia",         "Samoa"}, /* S (GMT-11:00) Midway Island, Samoa */
-
-    {"Pacific/Honolulu",     "Hawaiian"}, /* S (GMT-10:00) Hawaii */
-
-    {"America/Anchorage",    "Alaskan"}, /* D (GMT-09:00) Alaska */
-
-    {"America/Los_Angeles",  "Pacific"}, /* D (GMT-08:00) Pacific Time (US & Canada) */
-    {"America/Tijuana",      "Pacific Standard Time (Mexico)"}, /* S (GMT-08:00) Tijuana, Baja California */
-
-    {"America/Phoenix",      "US Mountain"}, /* S (GMT-07:00) Arizona */
-    {"America/Denver",       "Mountain"}, /* D (GMT-07:00) Mountain Time (US & Canada) */
-    {"America/Chihuahua",    "Mountain Standard Time (Mexico)"}, /* D (GMT-07:00) Chihuahua, La Paz, Mazatlan */
-
-    {"America/Managua",      "Central America"}, /* S (GMT-06:00) Central America */ /* America/Guatemala? */
-    {"America/Regina",       "Canada Central"}, /* S (GMT-06:00) Saskatchewan */
-    {"America/Mexico_City",  "Central Standard Time (Mexico)"}, /* D (GMT-06:00) Guadalajara, Mexico City, Monterrey */
-    {"America/Chicago",      "Central"}, /* D (GMT-06:00) Central Time (US & Canada) */
-
-    {"America/Indianapolis", "US Eastern"}, /* S (GMT-05:00) Indiana (East) */
-    {"America/Bogota",       "SA Pacific"}, /* S (GMT-05:00) Bogota, Lima, Quito */
-    {"America/New_York",     "Eastern"}, /* D (GMT-05:00) Eastern Time (US & Canada) */
-
-    {"America/Caracas",      "SA Western"}, /* S (GMT-04:00) Caracas, La Paz */
-    {"America/Santiago",     "Pacific SA"}, /* D (GMT-04:00) Santiago */
-    {"America/Halifax",      "Atlantic"}, /* D (GMT-04:00) Atlantic Time (Canada) */
-    {"America/Manaus",       "Central Brazilian"}, /* D (GMT-04:00 Manaus */
-
-    {"America/St_Johns",     "Newfoundland"}, /* D (GMT-03:30) Newfoundland */
-
-    {"America/Buenos_Aires", "SA Eastern"}, /* S (GMT-03:00) Buenos Aires, Georgetown */
-    {"America/Godthab",      "Greenland"}, /* D (GMT-03:00) Greenland */
-    {"America/Sao_Paulo",    "E. South America"}, /* D (GMT-03:00) Brasilia */
-    {"America/Montevideo",   "Montevideo"}, /* S (GMT-03:00) Montevideo */
-
-    {"America/Noronha",      "Mid-Atlantic"}, /* D (GMT-02:00) Mid-Atlantic */
-
-    {"Atlantic/Cape_Verde",  "Cape Verde"}, /* S (GMT-01:00) Cape Verde Is. */
-    {"Atlantic/Azores",      "Azores"}, /* D (GMT-01:00) Azores */
-
-    {"Africa/Casablanca",    "Greenwich"}, /* S (GMT) Casablanca, Monrovia */
-    {"Europe/London",        "GMT"}, /* D (GMT) Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London */
-
-    {"Africa/Lagos",         "W. Central Africa"}, /* S (GMT+01:00) West Central Africa */
-    {"Europe/Berlin",        "W. Europe"}, /* D (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna */
-    {"Europe/Paris",         "Romance"}, /* D (GMT+01:00) Brussels, Copenhagen, Madrid, Paris */
-    {"Eurpoe/Warsaw",        "Central European"}, /* D (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb */
-    {"Europe/Sarajevo",      "Central European"}, /* D (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb */
-    {"Europe/Prague",        "Central Europe"}, /* D (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague */
-    {"Europe/Belgrade",      "Central Europe"}, /* D (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague */
-
-    {"Africa/Johannesburg",  "South Africa"}, /* S (GMT+02:00) Harare, Pretoria */
-    {"Asia/Jerusalem",       "Israel"}, /* S (GMT+02:00) Jerusalem */
-    {"Europe/Istanbul",      "GTB"}, /* D (GMT+02:00) Athens, Istanbul, Minsk */
-    {"Europe/Helsinki",      "FLE"}, /* D (GMT+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius */
-    {"Africa/Cairo",         "Egypt"}, /* D (GMT+02:00) Cairo */
-    {"Europe/Minsk",         "E. Europe"}, /* D (GMT+02:00) Bucharest */
-    {"Europe/Bucharest",     "E. Europe"}, /* D (GMT+02:00) Bucharest */
-    {"Africa/Windhoek",      "Namibia"}, /* S (GMT+02:00) Windhoek */
-    {"Asia/Amman",           "Jordan"}, /* S (GMT+02:00) Aman */
-    {"Asia/Beirut",          "Middle East"}, /* S (GMT+02:00) Beirut */
-
-    {"Africa/Nairobi",       "E. Africa"}, /* S (GMT+03:00) Nairobi */
-    {"Asia/Riyadh",          "Arab"}, /* S (GMT+03:00) Kuwait, Riyadh */
-    {"Europe/Moscow",        "Russian"}, /* D (GMT+03:00) Moscow, St. Petersburg, Volgograd */
-    {"Asia/Baghdad",         "Arabic"}, /* D (GMT+03:00) Baghdad */
-
-    {"Asia/Tehran",          "Iran"}, /* D (GMT+03:30) Tehran */
-
-    {"Asia/Muscat",          "Arabian"}, /* S (GMT+04:00) Abu Dhabi, Muscat */
-    {"Asia/Tbilisi",         "Georgian"}, /* D (GMT+04:00) Tbilisi */
-    {"Asia/Baku",            "Azerbaijan"}, /* S (GMT+04:00) Baku */
-    {"Asia/Yerevan",         "Caucasus"}, /* S (GMT+04:00) Yerevan */
-    {"Asia/Kabul",           "Afghanistan"}, /* S (GMT+04:30) Kabul */
-
-    {"Asia/Karachi",         "West Asia"}, /* S (GMT+05:00) Islamabad, Karachi, Tashkent */
-    {"Asia/Yekaterinburg",   "Ekaterinburg"}, /* D (GMT+05:00) Ekaterinburg */
-
-    {"Asia/Calcutta",        "India"}, /* S (GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi */
-
-    {"Asia/Katmandu",        "Nepal"}, /* S (GMT+05:45) Kathmandu */
-
-    {"Asia/Colombo",         "Sri Lanka"}, /* S (GMT+06:00) Sri Jayawardenepura */
-    {"Asia/Dhaka",           "Central Asia"}, /* S (GMT+06:00) Astana, Dhaka */
-    {"Asia/Novosibirsk",     "N. Central Asia"}, /* D (GMT+06:00) Almaty, Novosibirsk */
-
-    {"Asia/Rangoon",         "Myanmar"}, /* S (GMT+06:30) Rangoon */
-
-    {"Asia/Bangkok",         "SE Asia"}, /* S (GMT+07:00) Bangkok, Hanoi, Jakarta */
-    {"Asia/Krasnoyarsk",     "North Asia"}, /* D (GMT+07:00) Krasnoyarsk */
-
-    {"Australia/Perth",      "W. Australia"}, /* S (GMT+08:00) Perth */
-    {"Asia/Taipei",          "Taipei"}, /* S (GMT+08:00) Taipei */
-    {"Asia/Singapore",       "Singapore"}, /* S (GMT+08:00) Kuala Lumpur, Singapore */
-    {"Asia/Shanghai",        "China"}, /* S (GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi */
-    {"Asia/Hong_Kong",       "China"}, /* S (GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi */
-    {"Asia/Ulaanbaatar",     "North Asia East"}, /* D (GMT+08:00) Irkutsk, Ulaan Bataar */
-    {"Asia/Irkutsk",         "North Asia East"}, /* D (GMT+08:00) Irkutsk, Ulaan Bataar */
-
-    {"Asia/Tokyo",           "Tokyo"}, /* S (GMT+09:00) Osaka, Sapporo, Tokyo */
-    {"Asia/Seoul",           "Korea"}, /* S (GMT+09:00) Seoul */
-    {"Asia/Yakutsk",         "Yakutsk"}, /* D (GMT+09:00) Yakutsk */
-
-    {"Australia/Darwin",     "AUS Central"}, /* S (GMT+09:30) Darwin */
-    {"Australia/Adelaide",   "Cen. Australia"}, /* D (GMT+09:30) Adelaide */
-
-    {"Pacific/Guam",         "West Pacific"}, /* S (GMT+10:00) Guam, Port Moresby */
-    {"Australia/Brisbane",   "E. Australia"}, /* S (GMT+10:00) Brisbane */
-    {"Asia/Vladivostok",     "Vladivostok"}, /* D (GMT+10:00) Vladivostok */
-    {"Australia/Hobart",     "Tasmania"}, /* D (GMT+10:00) Hobart */
-    {"Australia/Sydney",     "AUS Eastern"}, /* D (GMT+10:00) Canberra, Melbourne, Sydney */
-
-    {"Asia/Guadalcanal",     "Central Pacific"}, /* S (GMT+11:00) Magadan, Solomon Is., New Caledonia */
-    {"Asia/Magadan",         "Central Pacific"}, /* S (GMT+11:00) Magadan, Solomon Is., New Caledonia */
-
-    {"Pacific/Fiji",         "Fiji"}, /* S (GMT+12:00) Fiji, Kamchatka, Marshall Is. */
-    {"Pacific/Auckland",     "New Zealand"}, /* D (GMT+12:00) Auckland, Wellington */
-
-    {"Pacific/Tongatapu",    "Tonga"}, /* S (GMT+13:00) Nuku'alofa */
-    NULL,                    NULL
-};
-
-/**
- * If a lookup fails, we attempt to remap certain Windows ids to
- * alternate Windows ids.  If the alternate listed here begins with
- * '-', we use it as is (without the '-').  If it begins with '+', we
- * append a " Standard Time" if appropriate.
- */
-static const WindowsZoneRemap ZONE_REMAP[] = {
-    "Central European",                "-Warsaw",
-    "Central Europe",                  "-Prague Bratislava",
-    "China",                           "-Beijing",
-                                               
-    "Greenwich",                       "+GMT",
-    "GTB",                             "+GFT",
-    "Arab",                            "+Saudi Arabia",
-    "SE Asia",                         "+Bangkok",
-    "AUS Eastern",                     "+Sydney",
-    "Mountain Standard Time (Mexico)", "-Mexico Standard Time 2",
-    "Central Standard Time (Mexico)",  "+Mexico",
-    NULL,                   NULL,
-};
-
-static int32_t fWinType = -1;
+static int32_t gWinType = 0;
 
 static int32_t detectWindowsType()
 {
@@ -356,7 +101,7 @@
         really want to know is how the registry is laid out.
         Specifically, is it 9x/Me or not, and is it "GMT" or "GMT
         Standard Time". */
-    for (winType = 0; winType < 2; winType += 1) {
+    for (winType = 0; winType < 2; winType++) {
         result = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
                               WIN_TYPE_PROBE_REGKEY[winType],
                               0,
@@ -369,65 +114,30 @@
         }
     }
 
-    return winType;
-}
-
-/*
- * TODO: Binary search sorted ZONE_MAP...
- * (u_detectWindowsTimeZone() needs them sorted by offset...)
- */
-static const char *findWindowsZoneID(const UChar *icuid, int32_t length)
-{
-    char stackBuffer[ICUID_STACK_BUFFER_SIZE];
-    char *buffer = stackBuffer;
-    const char *result = NULL;
-    int i;
-
-    /*
-     * NOTE: >= because length doesn't include
-     * trailing null.
-     */
-    if (length >= ICUID_STACK_BUFFER_SIZE) {
-        buffer = NEW_ARRAY(char, length + 1);
-    }
-
-    u_UCharsToChars(icuid, buffer, length);
-    buffer[length] = '\0';
-
-    for (i = 0; ZONE_MAP[i].icuid != NULL; i += 1) {
-        if (uprv_strcmp(buffer, ZONE_MAP[i].icuid) == 0) {
-            result = ZONE_MAP[i].winid;
-            break;
-        }
-    }
-
-    if (buffer != stackBuffer) {
-        DELETE_ARRAY(buffer);
-    }
-
-    return result;
+    return winType+1; /* +1 to bring it inline with the enum */
 }
 
 static LONG openTZRegKey(HKEY *hkey, const char *winid)
 {
-    char subKeyName[96]; /* TODO: why 96?? */
+    char subKeyName[110]; /* TODO: why 96?? */
     char *name;
     LONG result;
 
-    /* TODO: This isn't thread safe, but it's probably good enough. */
-    if (fWinType < 0) {
-        fWinType = detectWindowsType();
+    /* This isn't thread safe, but it's good enough because the result should be constant per system. */
+    if (gWinType <= 0) {
+        gWinType = detectWindowsType();
     }
 
-    uprv_strcpy(subKeyName, TZ_REGKEY[(fWinType == WIN_9X_ME_TYPE) ? 0 : 1]);
+    uprv_strcpy(subKeyName, TZ_REGKEY[(gWinType != WIN_9X_ME_TYPE)]);
     name = &subKeyName[strlen(subKeyName)];
     uprv_strcat(subKeyName, winid);
 
-    if (fWinType != WIN_9X_ME_TYPE &&
-        (winid[strlen(winid) - 1] != '2') &&
-        (winid[strlen(winid) - 1] != ')') &&
-        !(fWinType == WIN_NT_TYPE && strcmp(winid, "GMT") == 0)) {
-        uprv_strcat(subKeyName, STANDARD_TIME_REGKEY);
+    if (gWinType == WIN_9X_ME_TYPE) {
+        /* Remove " Standard Time" */
+        char *pStd = uprv_strstr(subKeyName, STANDARD_TIME_REGKEY);
+        if (pStd) {
+            *pStd = 0;
+        }
     }
 
     result = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
@@ -435,27 +145,6 @@
                             0,
                             KEY_QUERY_VALUE,
                             hkey);
-
-    if (result != ERROR_SUCCESS) {
-        int i;
-
-        /* If the primary lookup fails, try to remap the Windows zone
-           ID, according to the remapping table. */
-        for (i=0; ZONE_REMAP[i].winid; i++) {
-            if (uprv_strcmp(winid, ZONE_REMAP[i].winid) == 0) {
-                uprv_strcpy(name, ZONE_REMAP[i].altwinid + 1);
-                if (*(ZONE_REMAP[i].altwinid) == '+' && fWinType != WIN_9X_ME_TYPE) {
-                    uprv_strcat(subKeyName, STANDARD_TIME_REGKEY);                
-                }
-                return RegOpenKeyExA(HKEY_LOCAL_MACHINE,
-                                      subKeyName,
-                                      0,
-                                      KEY_QUERY_VALUE,
-                                      hkey);
-            }
-        }
-    }
-
     return result;
 }
 
@@ -482,32 +171,31 @@
     return result;
 }
 
-U_CAPI UBool U_EXPORT2
-uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length)
-{
-    const char *winid;
-    TZI tzi;
+static LONG getSTDName(const char *winid, char *regStdName, int32_t length) {
+    DWORD cbData = length;
     LONG result;
-    
-    winid = findWindowsZoneID(icuid, length);
+    HKEY hkey;
 
-    if (winid != NULL) {
-        result = getTZI(winid, &tzi);
+    result = openTZRegKey(&hkey, winid);
 
-        if (result == ERROR_SUCCESS) {
-            zoneInfo->Bias         = tzi.bias;
-            zoneInfo->DaylightBias = tzi.daylightBias;
-            zoneInfo->StandardBias = tzi.standardBias;
-            zoneInfo->DaylightDate = tzi.daylightDate;
-            zoneInfo->StandardDate = tzi.standardDate;
+    if (result == ERROR_SUCCESS) {
+        result = RegQueryValueExA(hkey,
+                                    STD_REGKEY,
+                                    NULL,
+                                    NULL,
+                                    (LPBYTE)regStdName,
+                                    &cbData);
 
-            return TRUE;
-        }
     }
 
-    return FALSE;
+    RegCloseKey(hkey);
+
+    return result;
 }
 
+
+
+
 /*
   This code attempts to detect the Windows time zone, as set in the
   Windows Date and Time control panel.  It attempts to work on
@@ -562,13 +250,22 @@
  */
 U_CFUNC const char* U_EXPORT2
 uprv_detectWindowsTimeZone() {
+    UErrorCode status = U_ZERO_ERROR;
+    UResourceBundle* bundle = NULL;
+    char* icuid = NULL;
+    UChar apiStd[MAX_LENGTH_ID];
+    char apiStdName[MAX_LENGTH_ID];
+    char regStdName[MAX_LENGTH_ID];
+    char tmpid[MAX_LENGTH_ID];
+    int32_t len;
+    int id;
+    int errorCode;
+    char ISOcode[3]; /* 2 letter iso code */
+
     LONG result;
-    HKEY hkey;
     TZI tziKey;
     TZI tziReg;
     TIME_ZONE_INFORMATION apiTZI;
-    int firstMatch, lastMatch;
-    int j;
 
     /* Obtain TIME_ZONE_INFORMATION from the API, and then convert it
        to TZI.  We could also interrogate the registry directly; we do
@@ -583,24 +280,30 @@
     uprv_memcpy((char *)&tziKey.daylightDate, (char*)&apiTZI.DaylightDate,
            sizeof(apiTZI.DaylightDate));
 
-    /* For each zone that can be identified by Offset+Rules, see if we
-       have a match.  Continue scanning after finding a match,
-       recording the index of the first and the last match.  We have
-       to do this because some zones are not unique under
-       Offset+Rules. */
-    firstMatch = -1;
-    lastMatch = -1;
-    for (j=0; ZONE_MAP[j].icuid; j++) {
-        result = getTZI(ZONE_MAP[j].winid, &tziReg);
+    /* Convert the wchar_t* standard name to char* */
+    uprv_memset(apiStdName, 0, sizeof(apiStdName));
+    WideCharToMultiByte(CP_ACP,0, apiTZI.StandardName, -1, apiStdName, MAX_LENGTH_ID, NULL, NULL); 
+
+    tmpid[0] = 0;
+
+    id = GetUserGeoID(GEOCLASS_NATION);
+    errorCode = GetGeoInfo(id,GEO_ISO2,ISOcode,3,0);
+
+    bundle = ures_openDirect(NULL, "windowsZones", &status);
+    ures_getByKey(bundle, "mapTimezones", bundle, &status);
+
+    /* Note: We get the winid not from static tables but from resource bundle. */
+    while (U_SUCCESS(status) && ures_hasNext(bundle)) {
+        UBool idFound = FALSE;
+        const char* winid;
+        UResourceBundle* winTZ = ures_getNextResource(bundle, NULL, &status);
+        if (U_FAILURE(status)) {
+            break;
+        }
+        winid = ures_getKey(winTZ);
+        result = getTZI(winid, &tziReg);
 
         if (result == ERROR_SUCCESS) {
-            /* Assume that offsets are grouped together, and bail out
-               when we've scanned everything with a matching
-               offset. */
-            if (firstMatch >= 0 && tziKey.bias != tziReg.bias) {
-                break;
-            }
-
             /* Windows alters the DaylightBias in some situations.
                Using the bias and the rules suffices, so overwrite
                these unreliable fields. */
@@ -608,81 +311,63 @@
             tziKey.daylightBias = tziReg.daylightBias;
 
             if (uprv_memcmp((char *)&tziKey, (char*)&tziReg, sizeof(tziKey)) == 0) {
-                if (firstMatch < 0) {
-                    firstMatch = j;
+                const UChar* icuTZ = NULL;
+                if (errorCode != 0) {
+                    icuTZ = ures_getStringByKey(winTZ, ISOcode, &len, &status);
+                }
+                if (errorCode==0 || icuTZ==NULL) {
+                    /* fallback to default "001" and reset status */
+                    status = U_ZERO_ERROR;
+                    icuTZ = ures_getStringByKey(winTZ, "001", &len, &status);
                 }
 
-                lastMatch = j;
+                if (U_SUCCESS(status)) {
+                    /* Get the standard name from the registry key to compare with
+                       the one from Windows API call. */
+                    uprv_memset(regStdName, 0, sizeof(regStdName));
+                    result = getSTDName(winid, regStdName, sizeof(regStdName));
+                    if (result == ERROR_SUCCESS) {
+                        if (uprv_strcmp(apiStdName, regStdName) == 0) {
+                            idFound = TRUE;
+                        }
+                    }
+
+                    /* tmpid buffer holds the ICU timezone ID corresponding to the timezone ID from Windows.
+                     * If none is found, tmpid buffer will contain a fallback ID (i.e. the time zone ID matching
+                     * the current time zone information)
+                     */
+                    if (idFound || tmpid[0] == 0) {
+                        /* if icuTZ has more than one city, take only the first (i.e. terminate icuTZ at first space) */
+                        int index=0;
+                        while (! (*icuTZ == '\0' || *icuTZ ==' ')) {
+                            tmpid[index++]=*icuTZ++;
+                        }
+                        tmpid[index]='\0';
+                    }
+                }
             }
         }
+        ures_close(winTZ);
+        if (idFound) {
+            break;
+        }
     }
 
-    /* This should never happen; if it does it means our table doesn't
-       match Windows AT ALL, perhaps because this is post-XP? */
-    if (firstMatch < 0) {
-        return NULL;
+    /*
+     * Copy the timezone ID to icuid to be returned.
+     */
+    if (tmpid[0] != 0) {
+        len = uprv_strlen(tmpid);
+        icuid = (char*)uprv_malloc((len + 1) * sizeof(char));
+        uprv_memset(icuid, 0, len + 1);
+        if (icuid != NULL) {
+            uprv_strcpy(icuid, tmpid);
+        }
     }
+
+    ures_close(bundle);
     
-    if (firstMatch != lastMatch) {
-        char stdName[32];
-        DWORD stdNameSize;
-        char stdRegName[64];
-        DWORD stdRegNameSize;
-
-        /* Offset+Rules lookup yielded >= 2 matches.  Try to match the
-           localized display name.  Get the name from the registry
-           (not the API). This avoids conversion issues.  Use the
-           standard name, since Windows modifies the daylight name to
-           match the standard name if there is no DST. */
-        if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
-                              CURRENT_ZONE_REGKEY,
-                              0,
-                              KEY_QUERY_VALUE,
-                              &hkey) == ERROR_SUCCESS)
-        {
-            stdNameSize = sizeof(stdName);
-            result = RegQueryValueExA(hkey,
-                                     STANDARD_NAME_REGKEY,
-                                     NULL,
-                                     NULL,
-                                     (LPBYTE)stdName,
-                                     &stdNameSize);
-            RegCloseKey(hkey);
-
-            /*
-             * Scan through the Windows time zone data in the registry
-             * again (just the range of zones with matching TZIs) and
-             * look for a standard display name match.
-             */
-            for (j = firstMatch; j <= lastMatch; j += 1) {
-                stdRegNameSize = sizeof(stdRegName);
-                result = openTZRegKey(&hkey, ZONE_MAP[j].winid);
-
-                if (result == ERROR_SUCCESS) {
-                    result = RegQueryValueExA(hkey,
-                                             STD_REGKEY,
-                                             NULL,
-                                             NULL,
-                                             (LPBYTE)stdRegName,
-                                             &stdRegNameSize);
-                }
-
-                RegCloseKey(hkey);
-
-                if (result == ERROR_SUCCESS &&
-                    stdRegNameSize == stdNameSize &&
-                    uprv_memcmp(stdName, stdRegName, stdNameSize) == 0)
-                {
-                    firstMatch = j; /* record the match */
-                    break;
-                }
-            }
-        } else {
-            RegCloseKey(hkey); /* should never get here */
-        }
-    }
-
-    return ZONE_MAP[firstMatch].icuid;
+    return icuid;
 }
 
-#endif /* #ifdef U_WINDOWS */
+#endif 
diff --git a/source/common/wintz.h b/source/common/wintz.h
index 0704953..8a790a1 100644
--- a/source/common/wintz.h
+++ b/source/common/wintz.h
@@ -1,6 +1,6 @@
 /*
 ********************************************************************************
-*   Copyright (C) 2005-2007, International Business Machines
+*   Copyright (C) 2005-2012, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 ********************************************************************************
 *
@@ -26,9 +26,6 @@
 typedef struct _TIME_ZONE_INFORMATION TIME_ZONE_INFORMATION;
 U_CDECL_END
 
-U_CAPI UBool U_EXPORT2
-uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length);
-
 U_CFUNC const char* U_EXPORT2
 uprv_detectWindowsTimeZone();
 
diff --git a/source/data/misc/miscfiles.mk b/source/data/misc/miscfiles.mk
index e7b56ab..9647c68 100644
--- a/source/data/misc/miscfiles.mk
+++ b/source/data/misc/miscfiles.mk
@@ -1,4 +1,4 @@
-# *   Copyright (C) 2003-2007, International Business Machines
+# *   Copyright (C) 2003-2012, International Business Machines
 # *   Corporation and others.  All Rights Reserved.
 # A list of txt's to build
 # Note: 
@@ -23,4 +23,4 @@
 #
 
 MISC_SOURCE = \
-zoneinfo.txt supplementalData.txt metazoneInfo.txt
+zoneinfo.txt supplementalData.txt metazoneInfo.txt windowsZones.txt
diff --git a/source/data/misc/windowsZones.txt b/source/data/misc/windowsZones.txt
new file mode 100644
index 0000000..5235943
--- /dev/null
+++ b/source/data/misc/windowsZones.txt
@@ -0,0 +1,678 @@
+// ***************************************************************************
+// *
+// * Copyright (C) 2012 International Business Machines
+// * Corporation and others.  All Rights Reserved.
+// * Tool: org.unicode.cldr.icu.NewLdml2IcuConverter
+// * Source File: <path>/windowsZones.xml
+// *
+// ***************************************************************************
+windowsZones:table(nofallback){
+    mapTimezones{
+        "AUS Central Standard Time"{
+            001{"Australia/Darwin"}
+            AU{"Australia/Darwin"}
+        }
+        "AUS Eastern Standard Time"{
+            001{"Australia/Sydney"}
+            AU{"Australia/Sydney Australia/Melbourne"}
+        }
+        "Afghanistan Standard Time"{
+            001{"Asia/Kabul"}
+            AF{"Asia/Kabul"}
+        }
+        "Alaskan Standard Time"{
+            001{"America/Anchorage"}
+            US{
+                "America/Anchorage America/Juneau America/Nome America/Sitka America/"
+                "Yakutat"
+            }
+        }
+        "Arab Standard Time"{
+            001{"Asia/Riyadh"}
+            BH{"Asia/Bahrain"}
+            KW{"Asia/Kuwait"}
+            QA{"Asia/Qatar"}
+            SA{"Asia/Riyadh"}
+            YE{"Asia/Aden"}
+        }
+        "Arabian Standard Time"{
+            001{"Asia/Dubai"}
+            AE{"Asia/Dubai"}
+            OM{"Asia/Muscat"}
+            ZZ{"Etc/GMT-4"}
+        }
+        "Arabic Standard Time"{
+            001{"Asia/Baghdad"}
+            IQ{"Asia/Baghdad"}
+        }
+        "Argentina Standard Time"{
+            001{"America/Buenos_Aires"}
+            AR{
+                "America/Buenos_Aires America/Argentina/La_Rioja America/Argentina/Ri"
+                "o_Gallegos America/Argentina/Salta America/Argentina/San_Juan Americ"
+                "a/Argentina/San_Luis America/Argentina/Tucuman America/Argentina/Ush"
+                "uaia America/Catamarca America/Cordoba America/Jujuy America/Mendoza"
+            }
+        }
+        "Atlantic Standard Time"{
+            001{"America/Halifax"}
+            BM{"Atlantic/Bermuda"}
+            CA{"America/Halifax America/Glace_Bay America/Goose_Bay America/Moncton"}
+            GL{"America/Thule"}
+        }
+        "Azerbaijan Standard Time"{
+            001{"Asia/Baku"}
+            AZ{"Asia/Baku"}
+        }
+        "Azores Standard Time"{
+            001{"Atlantic/Azores"}
+            GL{"America/Scoresbysund"}
+            PT{"Atlantic/Azores"}
+        }
+        "Bahia Standard Time"{
+            001{"America/Bahia"}
+            BR{"America/Bahia"}
+        }
+        "Bangladesh Standard Time"{
+            001{"Asia/Dhaka"}
+            BD{"Asia/Dhaka"}
+            BT{"Asia/Thimphu"}
+        }
+        "Canada Central Standard Time"{
+            001{"America/Regina"}
+            CA{"America/Regina America/Swift_Current"}
+        }
+        "Cape Verde Standard Time"{
+            001{"Atlantic/Cape_Verde"}
+            CV{"Atlantic/Cape_Verde"}
+            ZZ{"Etc/GMT+1"}
+        }
+        "Caucasus Standard Time"{
+            001{"Asia/Yerevan"}
+            AM{"Asia/Yerevan"}
+        }
+        "Cen. Australia Standard Time"{
+            001{"Australia/Adelaide"}
+            AU{"Australia/Adelaide Australia/Broken_Hill"}
+        }
+        "Central America Standard Time"{
+            001{"America/Guatemala"}
+            BZ{"America/Belize"}
+            CR{"America/Costa_Rica"}
+            EC{"Pacific/Galapagos"}
+            GT{"America/Guatemala"}
+            HN{"America/Tegucigalpa"}
+            NI{"America/Managua"}
+            SV{"America/El_Salvador"}
+            ZZ{"Etc/GMT+6"}
+        }
+        "Central Asia Standard Time"{
+            001{"Asia/Almaty"}
+            AQ{"Antarctica/Vostok"}
+            IO{"Indian/Chagos"}
+            KG{"Asia/Bishkek"}
+            KZ{"Asia/Almaty Asia/Qyzylorda"}
+            ZZ{"Etc/GMT-6"}
+        }
+        "Central Brazilian Standard Time"{
+            001{"America/Cuiaba"}
+            BR{"America/Cuiaba America/Campo_Grande"}
+        }
+        "Central Europe Standard Time"{
+            001{"Europe/Budapest"}
+            AL{"Europe/Tirane"}
+            CZ{"Europe/Prague"}
+            HU{"Europe/Budapest"}
+            ME{"Europe/Podgorica"}
+            RS{"Europe/Belgrade"}
+            SI{"Europe/Ljubljana"}
+            SK{"Europe/Bratislava"}
+        }
+        "Central European Standard Time"{
+            001{"Europe/Warsaw"}
+            BA{"Europe/Sarajevo"}
+            HR{"Europe/Zagreb"}
+            MK{"Europe/Skopje"}
+            PL{"Europe/Warsaw"}
+        }
+        "Central Pacific Standard Time"{
+            001{"Pacific/Guadalcanal"}
+            AQ{"Antarctica/Macquarie"}
+            FM{"Pacific/Ponape Pacific/Kosrae"}
+            NC{"Pacific/Noumea"}
+            SB{"Pacific/Guadalcanal"}
+            VU{"Pacific/Efate"}
+            ZZ{"Etc/GMT-11"}
+        }
+        "Central Standard Time (Mexico)"{
+            001{"America/Mexico_City"}
+            MX{
+                "America/Mexico_City America/Bahia_Banderas America/Cancun America/Me"
+                "rida America/Monterrey"
+            }
+        }
+        "Central Standard Time"{
+            001{"America/Chicago"}
+            CA{
+                "America/Winnipeg America/Rainy_River America/Rankin_Inlet America/Re"
+                "solute"
+            }
+            MX{"America/Matamoros"}
+            US{
+                "America/Chicago America/Indiana/Knox America/Indiana/Tell_City Ameri"
+                "ca/Menominee America/North_Dakota/Beulah America/North_Dakota/Center"
+                " America/North_Dakota/New_Salem"
+            }
+            ZZ{"CST6CDT"}
+        }
+        "China Standard Time"{
+            001{"Asia/Shanghai"}
+            CN{"Asia/Shanghai Asia/Chongqing Asia/Harbin Asia/Kashgar Asia/Urumqi"}
+            HK{"Asia/Hong_Kong"}
+            MO{"Asia/Macau"}
+        }
+        "Dateline Standard Time"{
+            001{"Etc/GMT+12"}
+            ZZ{"Etc/GMT+12"}
+        }
+        "E. Africa Standard Time"{
+            001{"Africa/Nairobi"}
+            AQ{"Antarctica/Syowa"}
+            DJ{"Africa/Djibouti"}
+            ER{"Africa/Asmera"}
+            ET{"Africa/Addis_Ababa"}
+            KE{"Africa/Nairobi"}
+            KM{"Indian/Comoro"}
+            MG{"Indian/Antananarivo"}
+            SD{"Africa/Khartoum"}
+            SO{"Africa/Mogadishu"}
+            SS{"Africa/Juba"}
+            TZ{"Africa/Dar_es_Salaam"}
+            UG{"Africa/Kampala"}
+            YT{"Indian/Mayotte"}
+            ZZ{"Etc/GMT-3"}
+        }
+        "E. Australia Standard Time"{
+            001{"Australia/Brisbane"}
+            AU{"Australia/Brisbane Australia/Lindeman"}
+        }
+        "E. Europe Standard Time"{
+            001{"Asia/Nicosia"}
+            CY{"Asia/Nicosia"}
+        }
+        "E. South America Standard Time"{
+            001{"America/Sao_Paulo"}
+            BR{"America/Sao_Paulo"}
+        }
+        "Eastern Standard Time"{
+            001{"America/New_York"}
+            BS{"America/Nassau"}
+            CA{
+                "America/Toronto America/Iqaluit America/Montreal America/Nipigon Ame"
+                "rica/Pangnirtung America/Thunder_Bay"
+            }
+            TC{"America/Grand_Turk"}
+            US{
+                "America/New_York America/Detroit America/Indiana/Petersburg America/"
+                "Indiana/Vincennes America/Indiana/Winamac America/Kentucky/Monticell"
+                "o America/Louisville"
+            }
+            ZZ{"EST5EDT"}
+        }
+        "Egypt Standard Time"{
+            001{"Africa/Cairo"}
+            EG{"Africa/Cairo"}
+            PS{"Asia/Gaza Asia/Hebron"}
+        }
+        "Ekaterinburg Standard Time"{
+            001{"Asia/Yekaterinburg"}
+            RU{"Asia/Yekaterinburg"}
+        }
+        "FLE Standard Time"{
+            001{"Europe/Kiev"}
+            AX{"Europe/Mariehamn"}
+            BG{"Europe/Sofia"}
+            EE{"Europe/Tallinn"}
+            FI{"Europe/Helsinki"}
+            LT{"Europe/Vilnius"}
+            LV{"Europe/Riga"}
+            UA{"Europe/Kiev Europe/Simferopol Europe/Uzhgorod Europe/Zaporozhye"}
+        }
+        "Fiji Standard Time"{
+            001{"Pacific/Fiji"}
+            FJ{"Pacific/Fiji"}
+        }
+        "GMT Standard Time"{
+            001{"Europe/London"}
+            ES{"Atlantic/Canary"}
+            FO{"Atlantic/Faeroe"}
+            GB{"Europe/London"}
+            GG{"Europe/Guernsey"}
+            IE{"Europe/Dublin"}
+            IM{"Europe/Isle_of_Man"}
+            JE{"Europe/Jersey"}
+            PT{"Europe/Lisbon Atlantic/Madeira"}
+        }
+        "GTB Standard Time"{
+            001{"Europe/Bucharest"}
+            GR{"Europe/Athens"}
+            MD{"Europe/Chisinau"}
+            RO{"Europe/Bucharest"}
+        }
+        "Georgian Standard Time"{
+            001{"Asia/Tbilisi"}
+            GE{"Asia/Tbilisi"}
+        }
+        "Greenland Standard Time"{
+            001{"America/Godthab"}
+            GL{"America/Godthab"}
+        }
+        "Greenwich Standard Time"{
+            001{"Atlantic/Reykjavik"}
+            BF{"Africa/Ouagadougou"}
+            CI{"Africa/Abidjan"}
+            EH{"Africa/El_Aaiun"}
+            GH{"Africa/Accra"}
+            GM{"Africa/Banjul"}
+            GN{"Africa/Conakry"}
+            GW{"Africa/Bissau"}
+            IS{"Atlantic/Reykjavik"}
+            LR{"Africa/Monrovia"}
+            ML{"Africa/Bamako"}
+            MR{"Africa/Nouakchott"}
+            SH{"Atlantic/St_Helena"}
+            SL{"Africa/Freetown"}
+            SN{"Africa/Dakar"}
+            ST{"Africa/Sao_Tome"}
+            TG{"Africa/Lome"}
+        }
+        "Hawaiian Standard Time"{
+            001{"Pacific/Honolulu"}
+            CK{"Pacific/Rarotonga"}
+            PF{"Pacific/Tahiti"}
+            UM{"Pacific/Johnston"}
+            US{"Pacific/Honolulu"}
+            ZZ{"Etc/GMT+10"}
+        }
+        "India Standard Time"{
+            001{"Asia/Calcutta"}
+            IN{"Asia/Calcutta"}
+        }
+        "Iran Standard Time"{
+            001{"Asia/Tehran"}
+            IR{"Asia/Tehran"}
+        }
+        "Israel Standard Time"{
+            001{"Asia/Jerusalem"}
+            IL{"Asia/Jerusalem"}
+        }
+        "Jordan Standard Time"{
+            001{"Asia/Amman"}
+            JO{"Asia/Amman"}
+        }
+        "Kaliningrad Standard Time"{
+            001{"Europe/Kaliningrad"}
+            BY{"Europe/Minsk"}
+            RU{"Europe/Kaliningrad"}
+        }
+        "Korea Standard Time"{
+            001{"Asia/Seoul"}
+            KP{"Asia/Pyongyang"}
+            KR{"Asia/Seoul"}
+        }
+        "Magadan Standard Time"{
+            001{"Asia/Magadan"}
+            RU{"Asia/Magadan Asia/Anadyr Asia/Kamchatka"}
+        }
+        "Mauritius Standard Time"{
+            001{"Indian/Mauritius"}
+            MU{"Indian/Mauritius"}
+            RE{"Indian/Reunion"}
+            SC{"Indian/Mahe"}
+        }
+        "Middle East Standard Time"{
+            001{"Asia/Beirut"}
+            LB{"Asia/Beirut"}
+        }
+        "Montevideo Standard Time"{
+            001{"America/Montevideo"}
+            UY{"America/Montevideo"}
+        }
+        "Morocco Standard Time"{
+            001{"Africa/Casablanca"}
+            MA{"Africa/Casablanca"}
+        }
+        "Mountain Standard Time (Mexico)"{
+            001{"America/Chihuahua"}
+            MX{"America/Chihuahua America/Mazatlan"}
+        }
+        "Mountain Standard Time"{
+            001{"America/Denver"}
+            CA{
+                "America/Edmonton America/Cambridge_Bay America/Inuvik America/Yellow"
+                "knife"
+            }
+            MX{"America/Ojinaga"}
+            US{"America/Denver America/Boise America/Shiprock"}
+            ZZ{"MST7MDT"}
+        }
+        "Myanmar Standard Time"{
+            001{"Asia/Rangoon"}
+            CC{"Indian/Cocos"}
+            MM{"Asia/Rangoon"}
+        }
+        "N. Central Asia Standard Time"{
+            001{"Asia/Novosibirsk"}
+            RU{"Asia/Novosibirsk Asia/Novokuznetsk Asia/Omsk"}
+        }
+        "Namibia Standard Time"{
+            001{"Africa/Windhoek"}
+            NA{"Africa/Windhoek"}
+        }
+        "Nepal Standard Time"{
+            001{"Asia/Katmandu"}
+            NP{"Asia/Katmandu"}
+        }
+        "New Zealand Standard Time"{
+            001{"Pacific/Auckland"}
+            AQ{"Antarctica/South_Pole Antarctica/McMurdo"}
+            NZ{"Pacific/Auckland"}
+        }
+        "Newfoundland Standard Time"{
+            001{"America/St_Johns"}
+            CA{"America/St_Johns"}
+        }
+        "North Asia East Standard Time"{
+            001{"Asia/Irkutsk"}
+            RU{"Asia/Irkutsk"}
+        }
+        "North Asia Standard Time"{
+            001{"Asia/Krasnoyarsk"}
+            RU{"Asia/Krasnoyarsk"}
+        }
+        "Pacific SA Standard Time"{
+            001{"America/Santiago"}
+            AQ{"Antarctica/Palmer"}
+            CL{"America/Santiago"}
+        }
+        "Pacific Standard Time (Mexico)"{
+            001{"America/Santa_Isabel"}
+            MX{"America/Santa_Isabel"}
+        }
+        "Pacific Standard Time"{
+            001{"America/Los_Angeles"}
+            CA{"America/Vancouver America/Dawson America/Whitehorse"}
+            MX{"America/Tijuana"}
+            US{"America/Los_Angeles"}
+            ZZ{"PST8PDT"}
+        }
+        "Pakistan Standard Time"{
+            001{"Asia/Karachi"}
+            PK{"Asia/Karachi"}
+        }
+        "Paraguay Standard Time"{
+            001{"America/Asuncion"}
+            PY{"America/Asuncion"}
+        }
+        "Romance Standard Time"{
+            001{"Europe/Paris"}
+            BE{"Europe/Brussels"}
+            DK{"Europe/Copenhagen"}
+            ES{"Europe/Madrid Africa/Ceuta"}
+            FR{"Europe/Paris"}
+        }
+        "Russian Standard Time"{
+            001{"Europe/Moscow"}
+            RU{"Europe/Moscow Europe/Samara Europe/Volgograd"}
+        }
+        "SA Eastern Standard Time"{
+            001{"America/Cayenne"}
+            AQ{"Antarctica/Rothera"}
+            BR{
+                "America/Fortaleza America/Araguaina America/Belem America/Maceio Ame"
+                "rica/Recife America/Santarem"
+            }
+            FK{"Atlantic/Stanley"}
+            GF{"America/Cayenne"}
+            SR{"America/Paramaribo"}
+            ZZ{"Etc/GMT+3"}
+        }
+        "SA Pacific Standard Time"{
+            001{"America/Bogota"}
+            CA{"America/Coral_Harbour"}
+            CO{"America/Bogota"}
+            EC{"America/Guayaquil"}
+            HT{"America/Port-au-Prince"}
+            JM{"America/Jamaica"}
+            KY{"America/Cayman"}
+            PA{"America/Panama"}
+            PE{"America/Lima"}
+            ZZ{"Etc/GMT+5"}
+        }
+        "SA Western Standard Time"{
+            001{"America/La_Paz"}
+            AG{"America/Antigua"}
+            AI{"America/Anguilla"}
+            AW{"America/Aruba"}
+            BB{"America/Barbados"}
+            BL{"America/St_Barthelemy"}
+            BO{"America/La_Paz"}
+            BQ{"America/Kralendijk"}
+            BR{
+                "America/Manaus America/Boa_Vista America/Eirunepe America/Porto_Velh"
+                "o America/Rio_Branco"
+            }
+            CA{"America/Blanc-Sablon"}
+            CW{"America/Curacao"}
+            DM{"America/Dominica"}
+            DO{"America/Santo_Domingo"}
+            GD{"America/Grenada"}
+            GP{"America/Guadeloupe"}
+            GY{"America/Guyana"}
+            KN{"America/St_Kitts"}
+            LC{"America/St_Lucia"}
+            MF{"America/Marigot"}
+            MQ{"America/Martinique"}
+            MS{"America/Montserrat"}
+            PR{"America/Puerto_Rico"}
+            SX{"America/Lower_Princes"}
+            TT{"America/Port_of_Spain"}
+            VC{"America/St_Vincent"}
+            VG{"America/Tortola"}
+            VI{"America/St_Thomas"}
+            ZZ{"Etc/GMT+4"}
+        }
+        "SE Asia Standard Time"{
+            001{"Asia/Bangkok"}
+            AQ{"Antarctica/Davis"}
+            CX{"Indian/Christmas"}
+            ID{"Asia/Jakarta Asia/Pontianak"}
+            KH{"Asia/Phnom_Penh"}
+            LA{"Asia/Vientiane"}
+            MN{"Asia/Hovd"}
+            TH{"Asia/Bangkok"}
+            VN{"Asia/Saigon"}
+            ZZ{"Etc/GMT-7"}
+        }
+        "Samoa Standard Time"{
+            001{"Pacific/Apia"}
+            WS{"Pacific/Apia"}
+        }
+        "Singapore Standard Time"{
+            001{"Asia/Singapore"}
+            BN{"Asia/Brunei"}
+            ID{"Asia/Makassar"}
+            MY{"Asia/Kuala_Lumpur Asia/Kuching"}
+            PH{"Asia/Manila"}
+            SG{"Asia/Singapore"}
+            ZZ{"Etc/GMT-8"}
+        }
+        "South Africa Standard Time"{
+            001{"Africa/Johannesburg"}
+            BI{"Africa/Bujumbura"}
+            BW{"Africa/Gaborone"}
+            CD{"Africa/Lubumbashi"}
+            LS{"Africa/Maseru"}
+            LY{"Africa/Tripoli"}
+            MW{"Africa/Blantyre"}
+            MZ{"Africa/Maputo"}
+            RW{"Africa/Kigali"}
+            SZ{"Africa/Mbabane"}
+            ZA{"Africa/Johannesburg"}
+            ZM{"Africa/Lusaka"}
+            ZW{"Africa/Harare"}
+            ZZ{"Etc/GMT-2"}
+        }
+        "Sri Lanka Standard Time"{
+            001{"Asia/Colombo"}
+            LK{"Asia/Colombo"}
+        }
+        "Syria Standard Time"{
+            001{"Asia/Damascus"}
+            SY{"Asia/Damascus"}
+        }
+        "Taipei Standard Time"{
+            001{"Asia/Taipei"}
+            TW{"Asia/Taipei"}
+        }
+        "Tasmania Standard Time"{
+            001{"Australia/Hobart"}
+            AU{"Australia/Hobart Australia/Currie"}
+        }
+        "Tokyo Standard Time"{
+            001{"Asia/Tokyo"}
+            ID{"Asia/Jayapura"}
+            JP{"Asia/Tokyo"}
+            PW{"Pacific/Palau"}
+            TL{"Asia/Dili"}
+            ZZ{"Etc/GMT-9"}
+        }
+        "Tonga Standard Time"{
+            001{"Pacific/Tongatapu"}
+            KI{"Pacific/Enderbury"}
+            TK{"Pacific/Fakaofo"}
+            TO{"Pacific/Tongatapu"}
+            ZZ{"Etc/GMT-13"}
+        }
+        "Turkey Standard Time"{
+            001{"Europe/Istanbul"}
+            TR{"Europe/Istanbul"}
+        }
+        "US Eastern Standard Time"{
+            001{"America/Indianapolis"}
+            US{"America/Indianapolis America/Indiana/Marengo America/Indiana/Vevay"}
+        }
+        "US Mountain Standard Time"{
+            001{"America/Phoenix"}
+            CA{"America/Dawson_Creek America/Creston"}
+            MX{"America/Hermosillo"}
+            US{"America/Phoenix"}
+            ZZ{"Etc/GMT+7"}
+        }
+        "UTC"{
+            001{"Etc/GMT"}
+            GL{"America/Danmarkshavn"}
+            ZZ{"Etc/GMT"}
+        }
+        "UTC+12"{
+            001{"Etc/GMT-12"}
+            KI{"Pacific/Tarawa"}
+            MH{"Pacific/Majuro Pacific/Kwajalein"}
+            NR{"Pacific/Nauru"}
+            TV{"Pacific/Funafuti"}
+            UM{"Pacific/Wake"}
+            WF{"Pacific/Wallis"}
+            ZZ{"Etc/GMT-12"}
+        }
+        "UTC-02"{
+            001{"Etc/GMT+2"}
+            BR{"America/Noronha"}
+            GS{"Atlantic/South_Georgia"}
+            ZZ{"Etc/GMT+2"}
+        }
+        "UTC-11"{
+            001{"Etc/GMT+11"}
+            AS{"Pacific/Pago_Pago"}
+            NU{"Pacific/Niue"}
+            UM{"Pacific/Midway"}
+            ZZ{"Etc/GMT+11"}
+        }
+        "Ulaanbaatar Standard Time"{
+            001{"Asia/Ulaanbaatar"}
+            MN{"Asia/Ulaanbaatar Asia/Choibalsan"}
+        }
+        "Venezuela Standard Time"{
+            001{"America/Caracas"}
+            VE{"America/Caracas"}
+        }
+        "Vladivostok Standard Time"{
+            001{"Asia/Vladivostok"}
+            RU{"Asia/Vladivostok Asia/Sakhalin"}
+        }
+        "W. Australia Standard Time"{
+            001{"Australia/Perth"}
+            AQ{"Antarctica/Casey"}
+            AU{"Australia/Perth"}
+        }
+        "W. Central Africa Standard Time"{
+            001{"Africa/Lagos"}
+            AO{"Africa/Luanda"}
+            BJ{"Africa/Porto-Novo"}
+            CD{"Africa/Kinshasa"}
+            CF{"Africa/Bangui"}
+            CG{"Africa/Brazzaville"}
+            CM{"Africa/Douala"}
+            DZ{"Africa/Algiers"}
+            GA{"Africa/Libreville"}
+            GQ{"Africa/Malabo"}
+            NE{"Africa/Niamey"}
+            NG{"Africa/Lagos"}
+            TD{"Africa/Ndjamena"}
+            TN{"Africa/Tunis"}
+            ZZ{"Etc/GMT-1"}
+        }
+        "W. Europe Standard Time"{
+            001{"Europe/Berlin"}
+            AD{"Europe/Andorra"}
+            AT{"Europe/Vienna"}
+            CH{"Europe/Zurich"}
+            DE{"Europe/Berlin"}
+            GI{"Europe/Gibraltar"}
+            IT{"Europe/Rome"}
+            LI{"Europe/Vaduz"}
+            LU{"Europe/Luxembourg"}
+            MC{"Europe/Monaco"}
+            MT{"Europe/Malta"}
+            NL{"Europe/Amsterdam"}
+            NO{"Europe/Oslo"}
+            SE{"Europe/Stockholm"}
+            SJ{"Arctic/Longyearbyen"}
+            SM{"Europe/San_Marino"}
+            VA{"Europe/Vatican"}
+        }
+        "West Asia Standard Time"{
+            001{"Asia/Tashkent"}
+            AQ{"Antarctica/Mawson"}
+            KZ{"Asia/Oral Asia/Aqtau Asia/Aqtobe"}
+            MV{"Indian/Maldives"}
+            TF{"Indian/Kerguelen"}
+            TJ{"Asia/Dushanbe"}
+            TM{"Asia/Ashgabat"}
+            UZ{"Asia/Tashkent Asia/Samarkand"}
+            ZZ{"Etc/GMT-5"}
+        }
+        "West Pacific Standard Time"{
+            001{"Pacific/Port_Moresby"}
+            AQ{"Antarctica/DumontDUrville"}
+            FM{"Pacific/Truk"}
+            GU{"Pacific/Guam"}
+            MP{"Pacific/Saipan"}
+            PG{"Pacific/Port_Moresby"}
+            ZZ{"Etc/GMT-10"}
+        }
+        "Yakutsk Standard Time"{
+            001{"Asia/Yakutsk"}
+            RU{"Asia/Yakutsk"}
+        }
+    }
+}
diff --git a/source/i18n/windtfmt.cpp b/source/i18n/windtfmt.cpp
index 5e37e41..a83df50 100644
--- a/source/i18n/windtfmt.cpp
+++ b/source/i18n/windtfmt.cpp
@@ -1,6 +1,6 @@
 /*
 ********************************************************************************
-*   Copyright (C) 2005-2007, International Business Machines
+*   Copyright (C) 2005-2012, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 ********************************************************************************
 *
@@ -26,9 +26,12 @@
 #include "unicode/unistr.h"
 #include "unicode/ustring.h"
 #include "unicode/timezone.h"
+#include "unicode/basictz.h"
 #include "unicode/utmscale.h"
 
+#include "uassert.h"
 #include "cmemory.h"
+#include "putilimp.h"
 #include "uresimp.h"
 #include "windtfmt.h"
 #include "wintz.h"
@@ -307,6 +310,127 @@
     return zoneID;
 }
 
+static UBool getSystemTimeInformation(TimeZone *tz, SYSTEMTIME &daylightDate, SYSTEMTIME &standardDate, int32_t &bias, int32_t &daylightBias, int32_t &standardBias) {
+    UErrorCode status = U_ZERO_ERROR;
+    UBool result = TRUE;
+    BasicTimeZone *btz = (BasicTimeZone*)tz; // we should check type
+    InitialTimeZoneRule *initial = NULL;
+    AnnualTimeZoneRule *std = NULL, *dst = NULL;
+
+    btz->getSimpleRulesNear(uprv_getUTCtime(), initial, std, dst, status);
+    if (U_SUCCESS(status)) {
+        if (std == NULL || dst == NULL) {
+            bias = -1 * (initial->getRawOffset()/60000);
+            standardBias = 0;
+            daylightBias = 0;
+            // Do not use DST.  Set 0 to all stadardDate/daylightDate fields
+            standardDate.wYear = standardDate.wMonth  = standardDate.wDayOfWeek = standardDate.wDay = 
+            standardDate.wHour = standardDate.wMinute = standardDate.wSecond    = standardDate.wMilliseconds = 0;
+            daylightDate.wYear = daylightDate.wMonth  = daylightDate.wDayOfWeek = daylightDate.wDay =
+            daylightDate.wHour = daylightDate.wMinute = daylightDate.wSecond    = daylightDate.wMilliseconds = 0;
+        } else {
+            U_ASSERT(std->getRule()->getDateRuleType() == DateTimeRule::DOW);
+            U_ASSERT(dst->getRule()->getDateRuleType() == DateTimeRule::DOW);
+
+            bias = -1 * (std->getRawOffset()/60000);
+            standardBias = 0;
+            daylightBias = -1 * (dst->getDSTSavings()/60000);
+            // Always use DOW type rule
+            int32_t hour, min, sec, mil;
+            standardDate.wYear = 0;
+            standardDate.wMonth = std->getRule()->getRuleMonth() + 1;
+            standardDate.wDay = std->getRule()->getRuleWeekInMonth();
+            if (standardDate.wDay < 0) {
+                standardDate.wDay = 5;
+            }
+            standardDate.wDayOfWeek = std->getRule()->getRuleDayOfWeek() - 1;
+
+            mil = std->getRule()->getRuleMillisInDay();
+            hour = mil/3600000;
+            mil %= 3600000;
+            min = mil/60000;
+            mil %= 60000;
+            sec = mil/1000;
+            mil %= 1000;
+
+            standardDate.wHour = hour;
+            standardDate.wMinute = min;
+            standardDate.wSecond = sec;
+            standardDate.wMilliseconds = mil;
+
+            daylightDate.wYear = 0;
+            daylightDate.wMonth = dst->getRule()->getRuleMonth() + 1;
+            daylightDate.wDay = dst->getRule()->getRuleWeekInMonth();
+            if (daylightDate.wDay < 0) {
+                daylightDate.wDay = 5;
+            }
+            daylightDate.wDayOfWeek = dst->getRule()->getRuleDayOfWeek() - 1;
+
+            mil = dst->getRule()->getRuleMillisInDay();
+            hour = mil/3600000;
+            mil %= 3600000;
+            min = mil/60000;
+            mil %= 60000;
+            sec = mil/1000;
+            mil %= 1000;
+
+            daylightDate.wHour = hour;
+            daylightDate.wMinute = min;
+            daylightDate.wSecond = sec;
+            daylightDate.wMilliseconds = mil;
+        }
+    } else {
+        result = FALSE;
+    }
+
+    delete initial;
+    delete std;
+    delete dst;
+
+    return result;
+}
+
+static UBool getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length) {
+    UBool result = FALSE;
+    UnicodeString id = UnicodeString(icuid, length);
+    TimeZone *tz = TimeZone::createTimeZone(id);
+    
+    if (tz != NULL) {
+        int32_t bias;
+        int32_t daylightBias;
+        int32_t standardBias;
+        SYSTEMTIME daylightDate;
+        SYSTEMTIME standardDate;
+
+        if (getSystemTimeInformation(tz, daylightDate, standardDate, bias, daylightBias, standardBias)) {
+            uprv_memset(zoneInfo, 0, sizeof(TIME_ZONE_INFORMATION)); // We do not set standard/daylight names, so nullify first.
+            zoneInfo->Bias          = bias;
+            zoneInfo->DaylightBias  = daylightBias;
+            zoneInfo->StandardBias  = standardBias;
+            zoneInfo->DaylightDate  = daylightDate;
+            zoneInfo->StandardDate  = standardDate;
+
+            result = TRUE;
+        }
+    }
+
+    return result;
+}
+
+/*
+ * Given the timezone icuid, fill in zoneInfo by calling auxillary functions that creates a timezone and extract the 
+ * information to put into zoneInfo. This includes bias and standard time date and daylight saving date.
+ */
+U_CAPI UBool U_EXPORT2
+uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length)
+{
+    if (getWindowsTimeZoneInfo(zoneInfo, icuid, length)) {
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+
 U_NAMESPACE_END
 
 #endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/source/i18n/windtfmt.h b/source/i18n/windtfmt.h
index 869044e..d9c2531 100644
--- a/source/i18n/windtfmt.h
+++ b/source/i18n/windtfmt.h
@@ -1,6 +1,6 @@
 /*
 ********************************************************************************
-*   Copyright (C) 2005-2007, International Business Machines
+*   Copyright (C) 2005-2012, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 ********************************************************************************
 *
@@ -37,6 +37,9 @@
 
 U_NAMESPACE_BEGIN
 
+U_CAPI UBool U_EXPORT2
+uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length);
+
 class Win32DateFormat : public DateFormat
 {
 public: