bug-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Crash in TimeZone handling on windows


From: Roland Schwingel
Subject: Re: Crash in TimeZone handling on windows
Date: Tue, 06 Nov 2007 10:52:38 +0100
User-agent: Thunderbird 1.5.0.13 (Windows/20070809)

Hi...

A week ago I sent this patch for Windows timezone handling, but got no reaction up to now...

I don't want to hurry with it... I just want to ensure that it does not get lost... :-)

Thanks,

Roland

Roland Schwingel schrieb:
Hi...

On REAL japanese/polish/czech windows version gnustep crashes in TimeZone handling.
Contrary to western european windows versions the timezone names are encoded
in unicode in the windows registry in at least in these local versions. The present code
in GSWindowsTimeZone accesses the registry without taking care about unicode.

I fixed this by changing everything to unicode to be fully consistent and added the patch to my email.
This patch also obsoletes the FIXME section in this class... :-)

I hope it can be applied easily against trunk...

Thanks and keep on with your good work,

Roland


--- NSTimeZone.m 2007-10-26 16:05:50.000000000 +0200 +++ NSTimeZone.m.new 2007-10-29 09:47:20.000000000 +0100 @@ -2090,12 +2090,6 @@ int *hour, int *minute, int *second, int *mil); - -/* FIXME - * It's not unicode ... which is OK as the timezone registry - * names are ascii ... but we ought to be consistent. - */ - @implementation GSWindowsTimeZone - (NSString*) abbreviationForDate: (NSDate*)aDate @@ -2121,209 +2115,175 @@ - (id) initWithName: (NSString*)name data: (NSData*)data { - HKEY regDirKey; - BOOL isNT = NO; - BOOL regFound = NO; - - /* Open the key in the local machine hive where - * the time zone data is stored. */ - if (ERROR_SUCCESS == RegOpenKeyExA(HKEY_LOCAL_MACHINE, - "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones", - 0, - KEY_READ, - &regDirKey)) - { - isNT = YES; - regFound = YES; - } + HKEY regDirKey; + BOOL isNT = NO,regFound=NO; + + /* Open the key in the local machine hive where the time zone data is stored. */ + if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones", + 0, + KEY_READ, + &regDirKey)) + { + isNT=YES; + regFound=YES; + } else + { + if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones", + 0, + KEY_READ, + &regDirKey)) { - if (ERROR_SUCCESS == RegOpenKeyExA(HKEY_LOCAL_MACHINE, - "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones", - 0, - KEY_READ, - &regDirKey)) - { - regFound = YES; - } + regFound=YES; } + } if (regFound) - { - /* Iterate over all subKeys in the registry to find the right one. - Unfortunately name is a localized value. The keys in the registry are - unlocalized names. */ - CHAR achKey[255]; // buffer for subkey name - DWORD cbName; // size of name string - CHAR achClass[MAX_PATH] = ""; // buffer for class name - DWORD cchClassName = MAX_PATH; // size of class string - DWORD cSubKeys=0; // number of subkeys - DWORD cbMaxSubKey; // longest subkey size - DWORD cchMaxClass; // longest class string - DWORD cValues; // number of values for key - DWORD cchMaxValue; // longest value name - DWORD cbMaxValueData; // longest value data - DWORD cbSecurityDescriptor; // size of security descriptor - FILETIME ftLastWriteTime; // last write time - DWORD i; - DWORD retCode; - BOOL tzFound = NO; - - /* Get the class name and the value count. */ - retCode = RegQueryInfoKeyA( - regDirKey, // key handle - achClass, // buffer for class name - &cchClassName, // size of class string - NULL, // reserved - &cSubKeys, // number of subkeys - &cbMaxSubKey, // longest subkey size - &cchMaxClass, // longest class string - &cValues, // number of values for this key - &cchMaxValue, // longest value name - &cbMaxValueData, // longest value data - &cbSecurityDescriptor, // security descriptor - &ftLastWriteTime); // last write time - - if (cSubKeys && (retCode == ERROR_SUCCESS)) - { - const char *cName = [name cString]; - - for (i = 0; i < cSubKeys && !tzFound; i++) - { - cbName = 255; - - retCode = RegEnumKeyExA(regDirKey, - i, - achKey, - &cbName, - NULL, - NULL, - NULL, - &ftLastWriteTime); - if (retCode == ERROR_SUCCESS) - { - char keyBuffer[16384]; - HKEY regKey; - - if (isNT) - { - sprintf(keyBuffer, "SOFTWARE\\Microsoft\\Windows NT" - "\\CurrentVersion\\Time Zones\\%s", achKey); - } - else - { - sprintf(keyBuffer, "SOFTWARE\\Microsoft\\Windows" - "\\CurrentVersion\\Time Zones\\%s", achKey); - } - - if (ERROR_SUCCESS == RegOpenKeyExA(HKEY_LOCAL_MACHINE, - keyBuffer, - 0, - KEY_READ, - &regKey)) - { - char buf[256]; - char standardName[256]; - char daylightName[256]; - DWORD bufsize; - DWORD type; - - /* check standardname */ - standardName[0]='\0'; - bufsize=sizeof(buf); - if (ERROR_SUCCESS == RegQueryValueExA(regKey, - "Std", - 0, - &type, - buf, - &bufsize)) - { - strcpy(standardName, buf); - if (strcmp(standardName, cName) == 0) - tzFound = YES; - } - - /* check daylightname */ - daylightName[0]='\0'; - bufsize = sizeof(buf); - if (ERROR_SUCCESS == RegQueryValueExA(regKey, - "Dlt", - 0, - &type, - buf, - &bufsize)) - { - strcpy(daylightName, buf); - if (strcmp(daylightName, cName) == 0) - tzFound = YES; - } - - if (tzFound) - { - /* Read in the time zone data */ - bufsize = sizeof(buf); - if (ERROR_SUCCESS == RegQueryValueExA(regKey, - "TZI", - 0, - &type, - buf, - &bufsize)) - { - TZI *tzi = (void*)buf; - Bias = tzi->Bias; - StandardBias = tzi->StandardBias; - DaylightBias = tzi->DaylightBias; - StandardDate = tzi->StandardDate; - DaylightDate = tzi->DaylightDate; - } - - /* Set the standard name for the time zone. */ - if (strlen(standardName)) - { - int a, b; - - ASSIGN(timeZoneName, - [NSString stringWithUTF8String: standardName]); - - /* Abbr generated here is IMHO a - * bit suspicous but I kept it */ - for (a = 0, b = 0; standardName[a]; a++) - { - if (isupper(standardName[a])) - standardName[b++] = standardName[a]; - } - standardName[b] = 0; - ASSIGN(timeZoneNameAbbr, - [NSString stringWithUTF8String: standardName]); - } - - /* Set the daylight savings name for the time zone. */ - if (strlen(daylightName)) - { - int a, b; - - ASSIGN(daylightZoneName, - [NSString stringWithUTF8String: daylightName]); - - /* Abbr generated here is IMHO - * a bit suspicous but I kept it */ - for (a = 0, b = 0; daylightName[a]; a++) - { - if (isupper(daylightName[a])) - daylightName[b++] = daylightName[a]; + { + /* Iterate over all subKeys in the registry to find the right one. + Unfortunately name is a localized value. The keys in the registry are + unlocalized names. */ + wchar_t achKey[255]; // buffer for subkey name + DWORD cbName; // size of name string + wchar_t achClass[MAX_PATH] = L""; // buffer for class name + DWORD cchClassName = MAX_PATH; // size of class string + DWORD cSubKeys=0; // number of subkeys + DWORD cbMaxSubKey; // longest subkey size + DWORD cchMaxClass; // longest class string + DWORD cValues; // number of values for key + DWORD cchMaxValue; // longest value name + DWORD cbMaxValueData; // longest value data + DWORD cbSecurityDescriptor; // size of security descriptor + FILETIME ftLastWriteTime; // last write time + + DWORD i, retCode; + BOOL tzFound = NO; + + /* Get the class name and the value count. */ + retCode = RegQueryInfoKeyW( + regDirKey, // key handle + achClass, // buffer for class name + &cchClassName, // size of class string + NULL, // reserved + &cSubKeys, // number of subkeys + &cbMaxSubKey, // longest subkey size + &cchMaxClass, // longest class string + &cValues, // number of values for this key + &cchMaxValue, // longest value name + &cbMaxValueData, // longest value data + &cbSecurityDescriptor, // security descriptor + &ftLastWriteTime); // last write time + + if (cSubKeys && (retCode == ERROR_SUCCESS)) + { + wchar_t *wName = malloc(([name length]+1) * sizeof(wchar_t)); + if (wName) + { + [name getCharacters:wName]; + + for (i=0; i<cSubKeys && !tzFound; i++) + { + cbName = 255; + + retCode = RegEnumKeyExW(regDirKey, i, achKey, &cbName, NULL, NULL, NULL, &ftLastWriteTime); + if (retCode == ERROR_SUCCESS) + { + wchar_t keyBuffer[16384]; + HKEY regKey; + + if (isNT) + wcscpy(keyBuffer,L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\"); + else + wcscpy(keyBuffer,L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Time Zones\\"); + + wcscat(keyBuffer,achKey); + if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyBuffer, 0, KEY_READ, &regKey)) + { + wchar_t buf[256]; + wchar_t standardName[256]; + wchar_t daylightName[256]; + DWORD bufsize; + DWORD type; + + /* check standardname */ + standardName[0]=L'\0'; + bufsize=sizeof(buf); + if (ERROR_SUCCESS==RegQueryValueExW(regKey, L"Std", 0, &type, (BYTE *)buf, &bufsize)) + { + wcscpy(standardName,buf); + if (wcscmp(standardName,wName) == 0) + tzFound = YES; + } + + /* check daylightname */ + daylightName[0]=L'\0'; + bufsize=sizeof(buf); + if (ERROR_SUCCESS==RegQueryValueExW(regKey, L"Dlt", 0, &type, (BYTE *)buf, &bufsize)) + { + wcscpy(daylightName,buf); + if (wcscmp(daylightName,wName) == 0) + tzFound = YES; + } + + if (tzFound) + { + /* Read in the time zone data */ + bufsize=sizeof(buf); + if (ERROR_SUCCESS==RegQueryValueExW(regKey, L"TZI", 0, &type, (BYTE *)buf, &bufsize)) + { + TZI *tzi = (void*)buf; + Bias = tzi->Bias; + StandardBias = tzi->StandardBias; + DaylightBias = tzi->DaylightBias; + StandardDate = tzi->StandardDate; + DaylightDate = tzi->DaylightDate; + } + + /* Set the standard name for the time zone. */ + if (wcslen(standardName)) + { + int a, b; + ASSIGN(timeZoneName,[NSString stringWithCharacters:standardName length:wcslen(standardName)]); + + /* Abbr generated here is IMHO a bit suspicous but I kept it */ + for(a=0,b=0;standardName[a];a++) + { + if (iswupper(standardName[a])) + standardName[b++]=standardName[a]; + } + standardName[b]=L'\0'; + ASSIGN(timeZoneNameAbbr,[NSString stringWithCharacters:standardName length:wcslen(standardName)]); + } + + /* Set the daylight savings name for the time zone. */ + if (wcslen(daylightName)) + { + int a,b; + ASSIGN(daylightZoneName,[NSString stringWithCharacters:daylightName length:wcslen(daylightName)]); + + /* Abbr generated here is IMHO a bit suspicous but I kept it */ + for(a=0,b=0;daylightName[a];a++) + { + if (iswupper(daylightName[a])) + daylightName[b++]=daylightName[a]; + } + daylightName[b]=L'\0'; + ASSIGN(daylightZoneNameAbbr,[NSString stringWithCharacters:daylightName length:wcslen(daylightName)]); + } + } + RegCloseKey(regKey); + } + } } - daylightName[b] = 0; - ASSIGN(daylightZoneNameAbbr, - [NSString stringWithUTF8String: daylightName]); - } + + free(wName); } - RegCloseKey(regKey); - } - } - } - } + } RegCloseKey(regDirKey); - } + } + return self; }


reply via email to

[Prev in Thread] Current Thread [Next in Thread]