• #### When you change the insides, nobody notices

I find it ironic when people complain that Calc and Notepad haven't changed. In fact, both programs have changed. (Notepad gained some additional menu and status bar options. Calc got a severe workover.)

I wouldn't be surprised if these are the same people who complain, "Why does Microsoft spend all its effort on making Windows 'look cool'? They should spend all their efforts on making technical improvements and just stop making visual improvements."

And with Calc, that's exactly what happened: Massive technical improvements. No visual improvement. And nobody noticed. In fact, the complaints just keep coming. "Look at Calc, same as it always was."

The innards of Calc - the arithmetic engine - was completely thrown away and rewritten from scratch. The standard IEEE floating point library was replaced with an arbitrary-precision arithmetic library. This was done after people kept writing ha-ha articles about how Calc couldn't do decimal arithmetic correctly, that for example computing 10.21 - 10.2 resulted in 0.0100000000000016.

(These all came from people who didn't understand how computers handle floating point. I have a future entry planned to go into floating point representations in more detail.)

Today, Calc's internal computations are done with infinite precision for basic operations (addition, subtraction, multiplication, division) and 32 digits of precision for advanced operations (square root, transcendental operators).

Try it: 1 / 3 * 10000000000 - 3333333333 =. The result is one third exactly. Type 1/x - 3 = and you get zero back. (Of course, if you don't believe that, then repeat the sequence "* 10000000000 - 3333333333 =" until you're bored and notice that the answer always comes back as 0.33333333333333333333333333333333. If it were fixed-precision, then the 3's would eventually stop coming.)

Thirty-two positions of precision for inexact results not good enough? The Power Calculator PowerToy uses the same arithmetic engine as Calc and lets you crank the precision to an unimaginable 512 digits.

Anyway, my point is that - whether you like it or not - if you don't change the UI, nobody notices. That's so much effort is spent on new UI.

• #### The F*deral Bur*au of Inv*stigations

According to the Chicago Division,

Use of the NAME, INITIALS, or SEAL of the F*I
is restricted by law
and may be used only with written permission of the F*I.

Asterisks inserted to avoid being arrested by the F*I for using their name and initials without written permission.

(I hope they don't go after me for using their initials without permission late last year.)

• #### Extending the Internet Explorer context menu

In a comment, Darrell Norton asked for a "View in Mozilla" option for Internet Explorer.

Internet Explorer's context menu extension mechanism has been in MSDN for years. Let me show you how you can create this extension yourself.

First, create the following registry key:

[HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt\View in Mozilla]
@=REG_SZ:"C:\some\path\to\ViewInMozilla.htm"
Contexts=REG_DWORD:1


Of course, you need to change C:\some\path\to to an actual path.

How did I know to do this? Because steps 1, 2 and 3 in the "Implementation Steps" section tell me (1) what key to create, (2) what to set the default value to, and (3) what to set Contexts to. I chose a Context value of 1, which means "Default".

Okay, now to write the script ViewInMozilla.htm. Well, the documentation says that I can access context from the menuArguments property of the external object. So let's start with that.

<SCRIPT>
</SCRIPT>


Okay, let's run this puppy. Launch IE, right-click on a blank space in the web page, select "View in Mozilla", and you get...

    [object]


Woo-hoo! This is a major accomplishment: Something happened at all. Doing things in small steps makes it easy to identify where a problem is. If we had run full steam ahead to completion and then it didn't work, we wouldn't have known whether it was due to a bug in the script, a bad registration, a bad filename...

Now that I have the menu arguments, I can use that to suck out information about the item that the context menu applies to. Let's try this:

<SCRIPT>
</SCRIPT>


Woo-hoo, now it gives me the URL. Almost there. All that's left to do is to run a program with that URL as the command line parameter.

<SCRIPT>
var shell = new ActiveXObject("WScript.Shell");
shell.run("mozilla \"" + external.menuArguments.document.URL + "\"");
</SCRIPT>


Mission accomplished.

Now you too can create Internet Explorer context menu extensions.

In fact, go ahead and do it, since Darrell asked for it: Create an Internet Explorer context menu extension that operates on anchors and opens the linked-to page in Mozilla.

(Bonus: Tony Schreiner cooked up something similar for zooming.)

• #### Callback, the safety newsletter for the aviation community

Yes the "S" in NASA stands for "Space", but don't forget that the "A" stands for "Aeronautics". One of the programs that I (amateur aviation wannabe) find fascinating is the Aviation Safety Reporting System, where pilots can submit anonymous reports of "stupid things I have done" in order to teach other pilots "Don't do what I did."

• #### Do you know when your destructors run? Part 2.

Continuing from yesterday, here's another case where you have to watch your destructors. Yesterday's theme was destructors that run at the wrong time. Today, we're going to see destructors that don't run at all!

Assume there's an ObjectLock class which takes a lock in its constructor and releases it in its destructor.

DWORD ThreadProc(LPVOID p)
{
... do stuff ...
ObjectLock lock(p);
... do stuff ...
return 0;
}


Pretty standard stuff. The first batch of stuff is done without the lock, and the second batch is done inside the lock. When the function returns, the lock is automatically released.

But suppose somebody adds a little code to this function like this:

DWORD ThreadProc(LPVOID p)
{
... do stuff ...
ObjectLock lock(p);
...
...
return 0;
}


The code change was just to add an early exit if the object was cancelled.

But when does that ObjectLock destructor run?

It runs at the return statement, since that's when the lock goes out of scope. In particular, it is not run before you call ExitThread.

Result: You left an object locked permanently.

You can imagine how variations on this code could lead to resource leaks or other problems.

• #### You can do anything at zombo.com, anything at all

Zombo has been around for many years, and yet I still find it hilarious (requires Flash).

I just went back to check, and alas the introduction actually ends. But fortunately, they made it even cooler by having a text-only version. (Still requires sound.)

• #### Do you know when your destructors run? Part 1.

Larry Osterman discussed the importance of knowing when your global destructors run, but this problem is not exclusive to global objects. You need to take care even with local objects. Consider:

void Sample()
{
if (SUCCEEDED(CoInitialize(NULL))) {
CComPtr<IXMLDOMDocument> p;
if (SUCCEEDED(p.CoCreateInstance(CLSID_IXMLDOMDocument))) {
...
}
CoUninitialize();
}
}


Easy as pie. And there's a bug here.

When does the destructor for that smart-pointer run?

Answer: When the object goes out of scope, which is at the closing brace of the outer if statement, after the CoUninitialize call.

So you shut down COM, and then try to access a pointer to a COM object. This is not good. (Or as Larry describes it, "Blam!")

To fix this problem, you have to release all your COM pointers before the CoUninitialize. One way would be to insert a p.Release() at the end of the inner if. (But of course, if you're going to do that, then why bother using a smart pointer?)

Another fix would be to introduce a seemingly unnecessary scope:

void Sample()
{
if (SUCCEEDED(CoInitialize(NULL))) {
{
CComPtr<IXMLDOMDocument> p;
if (SUCCEEDED(p.CoCreateInstance(CLSID_IXMLDOMDocument))) {
...
}
} // ensure p is destructed before the CoUninit
CoUninitialize();
}
}


Make sure you leave that comment there or the next person to come across this code is going to "clean it up" by removing the "redundant" braces.

Of course, this is still too subtle. Here's another solution: Put the CoUninitialize inside a destructor of its own!

class CCoInitialize {
public:
CCoInitialize() : m_hr(CoInitialize(NULL)) { }
~CCoInitialize() { if (SUCCEEDED(m_hr)) CoUninitialize(); }
operator HRESULT() const { return m_hr; }
HRESULT m_hr;
};

void Sample()
{
CCoInitialize init;
if (SUCCEEDED(init)) {
CComPtr<IXMLDOMDocument> p;
if (SUCCEEDED(p.CoCreateInstance(CLSID_IXMLDOMDocument))) {
...
}
}
} // CoUninitialize happens here


This works even if you put the smart pointer at the same scope, as long as you put it after the CCoInitialize object:

void Sample()
{
CCoInitialize init;
CComPtr<IXMLDOMDocument> p;
if (SUCCEEDED(init) &&
SUCCEEDED(p.CoCreateInstance(CLSID_IXMLDOMDocument))) {
...
}
}


This works because objects with automatic storage duration are destructed in reverse order of declaration, so the object p wil be destructed first, then the object init.

Mind you, this is basically subtle no matter now you slice it. Nobody said programming was easy.

Tomorrow, part 2.

• #### Coffee machine or assault weapon?

Coffee Machine Assault Weapon
AK-47   X
M-90 Automatic X
KF550-BK X
XM15-E2S   X
• #### Beware the hash reset attack

There are a variety of message digest algorithms out there, MD5 being a particularly popular one. These generate a "message digest" (essentially, a hash) so you can detect whether somebody has tampered with a file, the theory being that it's hard to tamper with a file without changing its hash.

But make sure you record the file size as well as the digest.

Not that collisions are necessarily easy to create by mistake. (I've heard a rumor that the deployment team has seen an MD5 collision, but it's just a rumor. I have no evidence. Heck, maybe what really happened was that somebody on the deployment got their MR2 into a car accident...)

Anyway, the possibility of a "reset attack" makes collisions trivial to create.

Hash generators typically operate on a stream. The hash engine maintains some state. The file to be hashed is broken up into chunks, and each chunk is combined with the engine's state variables in some complex way. When you have passed all the data through the engine, you push a button on the engine and out pops the hash value (which is typically a copy of the state variables, or possibly a subset of them).

Now suppose somebody came up with a way of "resetting" the engine; that is, returning it to the initial state. Here's how they can make any document match your digest:

First, create an alternate message and send it through the hash engine.

Next, generate the bytes necessary to "reset" the engine.

Finally, append the original message.

In other words, the fake file looks like this:

[alternate message][garbage][original message]


where "garbage" is the reset.

This fake file has the same hash as the original message, since the "garbage" resets the hash engine to the initial state, at which point the replay of the original message regenerates the hash.

Result: A file with the same hash as the original, but with different content!

In a proper attack, of course, the "alternate message" would be crafted so the garbage and original mesage would be ignored. You might end it with a marker that means "Ignore everything after this point." (For HTML, you can just say <NOFRAMES> and everything after that point will be largely ignored by all modern browsers.) Many other file types encode the expected file length in the header, in which case you can append whatever garbage you want without having any effect.

But if you also store the file size with the hash, then the reset attack fails, because a reset attack always generates a file bigger than the original. To create a collision, they would have to create a shorter alternate message than the original, and then fiddle with the extra bytes to get the desired target hash to come out. This is significantly harder than just resetting.

(I'm not aware of anybody who has successfully been able to reset MD5, mind you. This is a protective measure: If somebody figures out how to reset MD5, a small bit of work on your side will prevent you from falling victim.)