Windows 7 Debugging Demo: Troubleshooting the Broken Microsoft Time Zone Utility

Earlier today, I received this request from a customer:

This ( is a .NET 1.1 app and I have installed .NET 1.1 SP1 on Windows 7 32-bit and all .NET 1.1 SP1 security patches but it doesn’t run. Gives me this error: An internal error has occurred: Object reference not set to an instance of an object” and then it quits.

Always being up for a challenge, I decided to have a look and see what wasn’t working. Reproducing the error is pretty straightforward. Just run the app – it’ll gladly crash for you. But the question is, why? And can you fix it?

If you hit this with a debugger, you’ll find the following stack when you hit an AV:

0:000> !dumpstack -ee
Current frame: (MethodDesc 0x2098d28 +0x1c SystemTimeZone.ConvertToTimeZoneInfoStructure)
ChildEBP RetAddr  Caller,Callee
0018f4f4 0206d4ab (MethodDesc 0x2098d08 +0x43 SystemTimeZone.ToLocalTime)
0018f55c 0206cfc0 (MethodDesc 0x2098cd8 +0x38 SystemTimeZone.Convert)
0018f574 0206a484 (MethodDesc 0x2e5680 +0x15c frmMain.ShowCurrentTimes_Click)
0018f5d8 02067686 (MethodDesc 0x2e56d0 +0x446 frmMain.frmMain_Load)
0018f61c 02060365 (MethodDesc 0x2e5620 +0x2ed frmMain.Main)

Now, you could take a stab at this with SOS and start pulling out objects, but I didn’t believe that this would be the easiest way to solve the problem. Instead, I decided to reverse engineer the code and have a look. If you take a peek at the structure you’re trying to create from the SystemTimeZone class, you’ll find where the instance of the time zone came from – the code was rampaging through the registry looking for it. Here’s the method in question:

public TimeZoneList()
    m_TZHash = new Hashtable();
    m_TZList = new ArrayList();
    RegistryKey key = Registry.LocalMachine.OpenSubKey(@”SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\”);
    string[] subKeyNames = key.GetSubKeyNames();
    Type t = typeof(TZIStructure);
    int num2 = Marshal.SizeOf(t);
    int num3 = subKeyNames.Length – 1;
    for (int i = 0; i <= num3; i++)
        RegistryKey key2 = key.OpenSubKey(subKeyNames[i]);
        SystemTimeZone zone = new SystemTimeZone();
        SystemTimeZone zone2 = zone;
        zone2.DaylightName = StringType.FromObject(key2.GetValue(“Dlt”));
        zone2.DisplayName = StringType.FromObject(key2.GetValue(“Display”));
        zone2.Index = IntegerType.FromObject(key2.GetValue(“Index“));
        zone2.MapId = StringType.FromObject(key2.GetValue(“MapID”));
        zone2.StandardName = StringType.FromObject(key2.GetValue(“Std”));
        zone2.Name = key2.Name.Substring(key2.Name.LastIndexOf(@”\”) + 1);
        zone2 = null;
        byte[] buffer = (byte[]) key2.GetValue(“TZI”);
        if ((buffer != null) && (buffer.Length >= num2))
            GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
            IntPtr ptr = handle.AddrOfPinnedObject();
            zone.TZI = (TZIStructure) Marshal.PtrToStructure(ptr, t);
            if (!m_TZHash.Contains(zone.Index))
                m_TZHash.Add(zone.Index, zone);

If you spend enough time with the !do command, you can eventually stumble upon the answer, but the easier approach is, again, to stay out of the debugger and leverage your favorite search engine. Here’s a KB article that points out the problem:

Relevant information: “The Index registry value does not exist in Windows Vista and in Windows Server 2008.”

Aha. See the source code above? It wants that value, and it’s not there. Root cause found.

Now, on to solutions.

First of all, I wonder if you need a solution at all. If you click on the clock, and then click on Change date and time settings… you will get to the Date and Time control panel. Click on the Additional Clocks tab, and you can add 2 additional clocks for 2 new time zones. If you need more, you can always use Gadgets to fill the rest of your needs. So, for most people, this should provide a built-in solution to the problem – you don’t need the app any more because the OS provides 2 solutions already.

But, if you really really love that particular app, you could always copy that piece of the registry from Windows XP onto your Windows 7 computer, drop it in a new place inside of the registry, and then use the VirtualRegistry shim to redirect that app’s checks of the timezone portion of the registry to the copy you brought over.

Special thanks to my friend Gov for pointing me to the KB article, and for coming up with the VirtualRegistry workaround idea.

Comments (11)

  1. someone says:

    Hey thanks. I am grateful.

  2. someone says:

    Hey but using that utility, I can’t change the Time Zone even if I run as admin or run without admin but with UAC virtualization disabled. One of the reasons I used that app is to quickly switch between Time Zones as I travel a lot and visit several countries. Now every time I have to go to the Control panel and several dialog boxes deep to change the time zone. And yes I know about tzutil but I prefer GUI.

  3. cjacks says:

    @someone – to change the time zone, the application would have to enable the SeTimeZonePrivilege first (which didn’t exist when it was written). They would have to change the code in order to make that bit work.

    Having travelled 40 times more miles on an airplane than I did in my car this year, I totally understand your desire for simplicity and similarly wish that the timezone switch was on the Date and Time control panel itself rather than sitting a dialog box past that.

  4. Mark Sowul says:

    I find it surprising that the Vista+ multiple time zones feature doesn’t let you "swap" the additional clocks with the current time zone.  So if you travel between "home" and "away" you have to change them both manually to each other.  

    I thought it would be a no-brainer to do this, if anyone actually thought through the use case of a multiple time zone feature.

  5. says:

    So why does it not work if I assign "Users" the right to "Change the system time" as shown in

  6. says:

    Sorry I mean "Change the time zone" above.

  7. cjacks says:

    @someone – you don’t need permission to change the system time, just the time zone. Standard users already have the privilege that allows them to change the time zone (beginning with Windows Vista), so you don’t need to change the group policy (and shouldn’t – changing the system time should be an admin operation). However, the application would need to take the privilege and enable it before it can use it – privileges come disabled until you explicitly enable them. That would require a code change.

  8. Does not work for me. I imported the XP registry subkey under HKCUSoftwareClassesVirtualStoreMACHINESOFTWAREMicrosoftWindows NTCurrentVersionTime Zones, VirtualRegistry is set. Any hints?

  9. OK, got it. I forgot the ADDREDIRECT parameter at first. Thank you!

  10. Abe says:

    I could not get the addrediret to work, can you please help to see what I am doing wrong. Trying this on a WinXp SP3.

    Create a new sdb for application reg.exe

    Select Virtual registry -> ADDREDIRECT(HKLMSoftwareA^HKCUSoftwareA)

    Create 2 keys HKLMSoftwareA & HKCUSoftwareA with default values as HKLA &HKCRA respectively

    right click and Install shim  

    Running> reg query KLMSoftwareA

    I was expecting to see results as HKCUA but get HKLMA instead. What am I doing wrong?

  11. cjacks says:

    @Abe – what you’re doing wrong is trying it on XP. We added that command line option in Windows Vista. Sorry I didn’t make that clear.