Monday, January 11, 2010

.NET Framework is a surprise box!!!

Most of the time when I need to get inspiration about how to do something, I turn to the inner bits and bolts of .NET Framework, because I think that there are a few hundred men-years worth of code there, and it does have some insights.

But, some times...

I was just looking into the Dictionary<TKey, TValue> class when I came across this little bit of code:
public virtual void GetObjectData(SerializationInfo info,
StreamingContext context)
{
if (info == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.info);
}
// ...
}

Ok, we don't have much here, and inside the .NET Framework there are lots and lots of helper classes to aggregate common functions and adhere to the D.R.Y. principle.

However, when I dove into the ThrowArgumentNullException method, this is what I've found:
internal static void ThrowArgumentNullException(ExceptionArgument argument)
{
throw new ArgumentNullException(GetArgumentName(argument));
}

The ExceptionArgument type is actually an enumeration, that lists the possible values for the method argument. Well, I thought that perhaps there were more than meets the eye here, but when I went through the GetArgumentName function... take a look:
internal static string GetArgumentName(ExceptionArgument argument)
{
switch (argument)
{
case ExceptionArgument.obj:
return "obj";

case ExceptionArgument.dictionary:
return "dictionary";

case ExceptionArgument.dictionaryCreationThreshold:
return "dictionaryCreationThreshold";

case ExceptionArgument.array:
return "array";

case ExceptionArgument.info:
return "info";

case ExceptionArgument.key:
return "key";

case ExceptionArgument.collection:
return "collection";

case ExceptionArgument.list:
return "list";

case ExceptionArgument.match:
return "match";

case ExceptionArgument.converter:
return "converter";

case ExceptionArgument.queue:
return "queue";

case ExceptionArgument.stack:
return "stack";

case ExceptionArgument.capacity:
return "capacity";

case ExceptionArgument.index:
return "index";

case ExceptionArgument.startIndex:
return "startIndex";

case ExceptionArgument.value:
return "value";

case ExceptionArgument.count:
return "count";

case ExceptionArgument.arrayIndex:
return "arrayIndex";

case ExceptionArgument.name:
return "name";

case ExceptionArgument.mode:
return "mode";
}
return string.Empty;
}

Ok, now you're thinking that the above function could be easily rewritten as:
internal static string GetArgumentName(ExceptionArgument argument)
{
return argument.ToString();
}

And perhaps the whole shebang of going through three different method calls could be avoided by simply writting:
public virtual void GetObjectData(SerializationInfo info,
StreamingContext context)
{
if (info == null)
{
throw new ArgumentNullException("info");
}
// ...
}

Right?!

Well that's what I thought... Until I read the source code.

Thanks to Microsoft the source code for the .NET Framework is public, so as I always like to learn, I've downloaded the full source and installed.

When I read the source for the ThrowHelper class, I've come across the following explanation:
The old way to throw an exception generates quite a lot 
IL code and assembly code.
Following is an example:

C# source

throw new ArgumentNullException("key",
Environment.GetResourceString("ArgumentNull_Key"));
IL code:
IL_0003: ldstr "key"
IL_0008: ldstr "ArgumentNull_Key"
IL_000d: call string System.Environment::GetResourceString(string)
IL_0012: newobj instance void System.ArgumentNullException::
.ctor(string,string)
IL_0017: throw

Which is 21bytes in IL.

So we want to get rid of the ldstr and call to
Environment.GetResource in IL.

In order to do that, I created two enums: ExceptionResource,
ExceptionArgument to represent the argument name and resource
name in a small integer. The source code will be changed to

ThrowHelper.ThrowArgumentNullException
(ExceptionArgument.key,
ExceptionResource.ArgumentNull_Key);

The IL code will be 7 bytes.

IL_0008: ldc.i4.4
IL_0009: ldc.i4.4
IL_000a: call void System.ThrowHelper::
ThrowArgumentNullException
(valuetype System.ExceptionArgument)
IL_000f: ldarg.0

This will also reduce the Jitted code size a lot.

After reading this I started having a little bit more respect for the guys that write this stuff.

Sunday, January 10, 2010

IIS7 Virtual FTP Servers problems and solutions

I know, I know, it's old news. After all IIS7 came out with Vista a couple years back, and with it came the possibility of having multiple virtual FTP servers in the same IIS.

But until now I had no idea of this, because, in all honesty, I skipped Windows Vista altogether. I didn't installed it in my box. Went straight from XP to Windows 7.

As I have some time in my hands, and after a complete reformat of my HD, I made a list of things that needed to be done. One of them is to rewrite the application that I use to update this site.

Part of this site is updated by using Blogger.com, but another part is by a program I made myself. This program was written almost five years ago, so a LOT of things have evolved since then.

I'm currently upgrading it to Visual Studio 2010 Beta2, along with a complete, no old code, rewrite of my ancient FTP Library.

I'm not going into details of this new library (which I will post as it's ready), but during my basic tests I wasn't able to connect to my own local server, because I have set it up as a virtual FTP server, complete, with host name (that I updated the Windows\system32\drivers\etc\hosts file to emulate a live FQDN server) and login users and permissions.

When I tried to connect, I got a "530-Valid hostname is expected." error.

What the heck?!

Because I had never played with the new IIS7 before, I thought it would handle the host name binding behind the scenes (as I have set up just a single FTP server) as the IIS does normally for the HTTP protocol.

And hence the problem. The the FTP protocol, although extensible, does not provide means to infer directly the host name for an specific connection.

For example: let's say we create two virtual FTP servers one for the FQDN ftp.example.com and another for ftp.contoso.com.

Both these virtual servers points to the same IP. And each of these virtual servers points to different location in the same server (it could even be in another server, but let's keep it simple for argument's sake).

Now, let's say that the users allowed to access ftp.example.com DO NOT have access to ftp.contoso.com.

When an FTP client connects to a full qualified domain name (like ftp.example.com) it actually makes a connection to the IP that is represented by that name (your basic DNS service) and, usually, on port 21.

After a connection is established, the FTP server sends a simple reply "220 Connection OK".

At this point the FTP server have NO IDEA of what FQDN the client requested. There's no way to tell. It can't even make a DNS reverse lookup, because the all the server knows at this point is that a client is connected to an specific listening port, bound to an specific address (or not so specific -- as you can set the binding to listen on all server's address).

So there are two approaches:
  • The FTP client sends a "HOST" command to specify which virtual host it's addressing;

  • Or it issues a "USER virtual.host|userName" command

Older FTP clients are not prepared for this kind of situation.

And not all the newer ones are ready for this.

As an workaround Robert McMurray proposed back in '08 to use a "Global Listener FTP Site" which it's nothing more than an unbidden FTP site that routes users to the appropriated paths.

However this approach isn't a solution as it doesn't resolve the problem of a single user that have access to more than one FTP virtual server.

So, to wrap it up, the "virtual.host|userName" approach to connect to an FTP virtual server, is the best fall back solution for older FTP clients that are not aware of the new HOST command, and gives their users a possible mean of connection.

Saturday, January 09, 2010

Windows Experience Index

Two days ago I've got a faulty HDD that was making my computer slow to a craw. Well, I didn't know it back then and I thought it was simply a case of much needed reformat.

After a couple of hours battling the Windows 7 install, I discovered the faulty HDD, and as it was an old 60GB that was lingering with no vital data whatsoever, I simply plug it off and the installation went in its merry way.

After everything was configured I needed to configure some Environment Variables and pressed Win+Break to bring me the necessary interface and noticed the Windows Experience Index of my little box.

Although I really don't give much of a thought about my WEI score, it just occurred me what would it takes to get the perfect (and so far somewhat mythical) 7.9 score.

A little bit of searching gave me some start points.

In short what would you need to achieve the perfect 7.9 score would be something like the following specification:

Processor:

Intel Core i7 975 Extreme Edition running at a whopping 4GHz

Memory:

At least 12GB of DDR3-2000 triple channel

Graphics:

Two Radeon 5970 in a crossfire configuration

Hard disk:

???


Yep, no known HDD configuration so far has been able to achieve the mythical 7.9 score in Windows 7. I've seen reports that even with two SSD drives in a RAID0 configuration the best score it achieved was 6.5.

Except for the hard disk configuration, all other items are feasible today, if not cheap.

Let's see how much:

ItemDescriptionPrice
ProcessorIntel Core i7 975 Extreme Edition$ 969.99
Memory6 GB DDR-20002 x $199.99
GraphicsRadeon 59702 x $ 649.99
Total$ 2,021.96

And I didn't even included a compatible motherboard. :-P

Tuesday, January 05, 2010

I'm perplexed!

I've just received an update email from Microsoft about the Vista Icon bug I have reported.

Even though this bug has been lurking in .NET Framework ever since version 2.0, and that I have provided them with a fixed version of their own code, the status was changed to "Won't Fix"

What the heck?!

Monday, January 04, 2010

Vista Icons in .NET

As I have posted earlier, the .NET Framework has a problem with the 256x256 PNG icons that were introduced with Windows Vista.

I posted a bug report on Microsoft Connect explaining my findings and pointing them to my blog. They kindly mailed me earlier today that they were able to reproduce the behavior and are redirecting to the appropriated team.

I hope this time they will fix it, as I have done all the heavy lifting. Hehe!

Anyway, the basic problem with the System.Drawing.Icon class is the Initialize method. It searches for the wrong parameters (that I believe were right at the time).

Because the way it searchs for the difference in the icon size and the requested size AND the fact that a 256x256 icon reports its size, in the icon file structure, as 0x0, I was able to get an icon with 256x256 from the System.Drawing.Icon object by using a little bit of ingenuity: by asking for a 1x1 icon.

But although the Icon object reported its size as 256x256, when I called the ToBitmap() function, in order to get a proper image, an Exception was thrown.

However when I used a custom size of 255x255 PNG icon... The Icon class was able to get it right away. No need to work around anything.

So, if you need to have a 256x256 PNG icon in your .NET application AND have control of what icon you use, start using 255x255 custom sized icons instead.

Sunday, January 03, 2010

Message to Microsoft

As reported by several people, the TypeConverter base class is broken. The IsValid function ALWAYS returns true, unless overridden by a derived class.

I understand that changing the behavior of the IsValid function would be a breaking change, but as the TypeConverter base class DOES NOT KNOW IF A VALUE IS VALID OR NOT, it should always return FALSE!!

That's the most logical approach.

I believe that when the TypeConverter class was being written back in the day, the programmer simply put a "return true;" to make it easy for him to do the tests that he was performing, and forgot to change it back before the shipping date.

I also firmly believe that the automated tests at that time didn't have any negative tests, i.e., tests that are OK if the method FAILS, and therefore that little bug escaped by the cracks of the dam.

So, once more, I think that the bug should be fixed and I strongly believe that no real life application will be broken in any way because any application that performed a negative test on the IsValid function on any custom TypeConverter derived class would have found that bug and fixed before shipping.

Finally, making another heartfelt appeal FIX THE DAMN BUG!!!

TypeConverter class is broken!

Well, sort of.

I was browsing the Connect site and got a glimpse of this reported bug.

Digging a bit in the Framework I discovered that EVERY TypeConverter based class that does not override the IsValid function will always return TRUE.

The bug resides in the base TypeConverter class that has the following code:
public virtual bool IsValid(ITypeDescriptorContext context, object value)
{
return true;
}

Hence, every single TypeDescriptor that doesn't override it, will fail the most basic tests.

Shame on you MS.

So, if you ever need to create a TypeConverter derived class, ALWAYS override the IsValid function.

Saturday, January 02, 2010

EventHandlers in VB: How to pass them around.

I was implementing an special INotifyCollectionChanged when I needed to know if the instance had event handlers attached.

After a little bit of searching, I took a page out of the ObservableCollecion(Of T) in order to do it.

In order to detect if YOUR class has event handlers attached, you need to create a Custom Event. Something like this:
Private __MyEventHandler as EventHandler 

Public Custom Event MeEvent As EventHandler
AddHandler(ByVal value As EventHandler)
Dim handler2 As EventHandler
Dim myEventHandler = __MyEventHandler
Do
handler2 = canExecuteCommand
Dim handler3 = DirectCast( _
System.Delegate.Combine(handler2, value), _
EventHandler)
myEventHandler = Interlocked.CompareExchange( _
(__MyEventHandler), handler3, handler2)
Loop While (Not myEventHandler Is handler2)
__MyEventHandler = myEventHandler
End AddHandler
RemoveHandler(ByVal value As EventHandler)
Dim handler2 As EventHandler
Dim myEventHandler = __MyEventHandler
Do
handler2 = canExecuteCommand
Dim handler3 = DirectCast( _
System.Delegate.Remove(handler2, value), _
EventHandler)
myEventHandler = Interlocked.CompareExchange( _
(__MyEventHandler), handler3, handler2)
Loop While (Not myEventHandler Is handler2)
__MyEventHandler = myEventHandler
End RemoveHandler
RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)
If (__MyEventHandler IsNot Nothing) Then
__MyEventHandler.Invoke(sender, e)
End If
End RaiseEvent
End Event

Custom Events are available to VB programmers ever since .NET Framework 2.0 along with Visual Studio 2005, although it's not very used, due to the fact that simply declaring an event and using AddHanlder, RemoveHandler and RaiseEvent solve most of day-to-day event problems.

But when we need something different, it's good to know it's available to us.