[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Crash in TimeZone handling on windows
From: |
Roland Schwingel |
Subject: |
Crash in TimeZone handling on windows |
Date: |
Mon, 29 Oct 2007 10:18:50 +0100 |
User-agent: |
Thunderbird 1.5.0.13 (Windows/20070809) |
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,
- ®DirKey))
- {
- 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,
+ ®DirKey))
+ {
+ isNT=YES;
+ regFound=YES;
+ }
else
+ {
+ if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
+ 0,
+ KEY_READ,
+ ®DirKey))
{
- if (ERROR_SUCCESS == RegOpenKeyExA(HKEY_LOCAL_MACHINE,
- "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
- 0,
- KEY_READ,
- ®DirKey))
- {
- 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,
- ®Key))
- {
- 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, ®Key))
+ {
+ 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;
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Crash in TimeZone handling on windows,
Roland Schwingel <=