Home | Blog | Publications | Photos | Services | About | Contact

Blog Archive - July, 2006

Back to Blog index.

Fri, 28 Jul 2006 06:16:07 GMT:
Introduction to XAML data binding

I today ran across an older article about Windows Presentation Foundation (WPF, aka Avalon) data binding from May. In this two-part article series, Shawn Wildermuth introduces the concept of binding data to XAML components. Recommended reading!

Here's Part 1 and Part 2.

Thu, 27 Jul 2006 12:20:43 GMT:
Prepare for HTTPS modifications in IE7 and WinInet libraries

As you are surely aware, Windows Vista will come with a new version of Internet Explorer, version 7. This new version improves, among other things, security in many ways. One of these modifications is the handling of sites that use HTTPS or SSL certificates.

On MSDN, there's an article about these changes. Even if you don't run a web site that uses HTTPS, your applications might be affected, too. This is because the changes are made in the WinInet libraries, which IE uses. And your application or library code might, too. For example, Delphi web services code might be affected.

Mon, 24 Jul 2006 07:49:44 GMT:
Warning about Corel Download Manager and Windows Vista

I today noticed that you need to be careful with certain ActiveX controls that you run with Internet Explorer (IE) 7.0 in Windows Vista (I'm using Beta 2, build 5384 for this). I was about to try Corel's Paint Shop Pro X, and one can find a free trial version from their web site.

The problem with Corel is that you need to install their download manager to get any downloads from them. They use Netopsystems' Get, which is a "1-Click Download and Installation Manager" according to their site. Well, the problem is that it doesn't work property on Windows Vista.

The problem is that the download manager doesn't give you any chance to select the download directory, and instead chooses the desktop for you. But because of IE7's Protected Mode (I believe), the ActiveX download manager newer has the ability to write to my desktop, and instead the path gets virtualized. However, it took me a while to find this location, since it is a bit tricky:

C:\Users\Jani Järvinen\AppData\Local\Microsoft\Windows\Temporary Internet Files\Virtualized\C\Users\Jani Järvinen\Desktop\PaintShopProX

As you can see, with Vista loose security practices are gone. And I like that; instead of blaming Microsoft, I blame Corel for a) forcing me to use their download manager, and b) not allowing me to select where I want to save my stuff. I just hate when things like this happen. And, it's the first day of my three-week summer vacation.

Thu, 20 Jul 2006 16:23:43 GMT:
Another great ASP.NET article from Scott Mitchell

Scott Mitchell seems to be in good mood, as he has recently published lately many excellent introductory ASP.NET/ADO.NET tutorial. Go check his latest article, "Implementing Optimistic Concurrency".

Tue, 18 Jul 2006 15:58:11 GMT:
Mark Russinovich now at Microsoft

SysInternals, the makers of the famous free and often very much needed low-level utilities (like RegMon and FileMon) today announced that it was bought by Microsoft. Congratulations, Mark! Also, for Microsoft Mark is definitely a great addition to their staff. I'm happy things turned out this way.

Tue, 18 Jul 2006 14:06:54 GMT:
BDS 2006 and compiler directives separation character

I today noticed a minor problem with BDS 2006: whenever you have more than one compiler directive defined, you need to pay attention to the separator character you use. Especially, if you are moving your code from an earlier version of Delphi, this issue might bite you.

The problem is that if you use Borland Developer Studio 2006 to define more than one compiler directive (for conditional compilation with $IFDEF for example) using the Project Properties window, you must use the semicolon ";" to separate your entries. However, the DCC compiler itself is happy with a comma as well, but the IDE isn't. This can lead to problems with code that actually compiles, but behaves wrong when you want for example to refactor it. If you have code within $IFDEFs, and have enabled a conditional symbol but used the comma to do so, the refactoring features believes you don't have the conditional defined, and thus leaves your $IFDEFed code intact.

Mon, 17 Jul 2006 14:11:49 GMT:
My TDM article about Volume Shadow Copy Service and Windows XP

In September 2005, I wrote an article to The Delphi Magazine about Windows' Volume Shadow Copy service, or VSS. My article, titled "Delphi Meets The Volume Shadow Copy Service" has become quite popular it seems; some readers subscribing to the magazine just for my article alone. Good.

Now, lately I've also received many questions from readers about the sample application I provided with the article. Now, the article was written with Windows Server 2003 (W2K3) in mind, even though Windows XP also supports VSS. The question I get is "how can I modify the sample application to work with Windows XP?"

Since this is such a common question, I thought I'd briefly share what you need to do. First of all, you would need to get the Windows XP versions of the C++ .H header files. My sample code includes the .H files for W2K3, but you may find the needed files from the SDK. You would need to check which interfaces are different on WinXP compared to W2K3. Secondly, you need to change the declaration of the CreateVssBackupComponents API function in the VssAPI.pas unit in my sample code. For W2K3, this function is defined at index 13, but on WinXP this function is defined at index 5. Hope this helps!

Fri, 14 Jul 2006 15:01:17 GMT:
More free virtualization software

On Wednesday, Microsoft announces that it will give its desktop virtualization software, Virtual PC, for free. Today, VMware continued the same game as it announced that it's former VMware GSX Server product -- with the about $1500 price tag -- is now available as a free product called VMware Server.

As a developer, I won't complain. But this boom of free virtualization software just shows how important virtualization has come. Now it's the time to get it to the masses.

Wed, 12 Jul 2006 17:13:31 GMT:
Microsoft makes Virtual PC a free product

Although I've previously been a VMware user (as I think it is better than Microsoft's offering), pricing also has some effect on me. I noticed just today that Microsoft has made Virtual PC 2004 Service Pack 1 a free download on their site. They also state that Virtual PC 2007 will be free. But what is going to happen after that, I don't yet know.

Mon, 10 Jul 2006 15:22:53 GMT:
A short primer on Intel's EMT64 technology

Intel has published a nice introductory article about their Extended Memory 64 Technology (EMT64) for developers. Recommended reading even though you are using managed code for instance with C#.

Sun, 09 Jul 2006 17:10:35 GMT:
Understanding why a ASP.NET page doesn't display special characters like "åäö" correctly

Recently, I ran into an issue with an ASP.NET 1.1 web application built with Delphi 2006 and Dreamweaver MX 2004 that had problems showing Finnish national characters like å, ä, and ö. These special characters were always displayed as garbage on the web browser, and so I had to investigate.

At first sight, all appeared to be OK. The .aspx pages were encoded in UTF-8 (Unicode), there was a proper meta tag for older browsers, and ASP.NET was configured with the web.config "globalization" element to return the pages in said UTF-8. Still, Internet Explorer displayed these special characters as garbage. The issue had been solved so far by using HTML entities, i.e. by using codes like "ä" for "ä", and so forth.

To test the issue, I built a very simple ASP.NET page with just basic HTML code inside, and to have these special characters there:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>UTF-8 Test</title>
</head>

<body>
Test: åäö
</body>
</html>

Next, I tested with telnet.exe to see how this page was returned by the server. As expected, the command returned output like this:

GET /test-utf8.aspx HTTP/1.0

HTTP/1.1 200 OK
Connection: close
Date: Tue, 11 Jul 2006 09:00:42 GMT
Server: Microsoft-IIS/6.0
X-Developed-With: Delphi
P3P: CP="PHYo ONLo CONo TELo SAMo"
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 274

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>UTF-8 Test</title>
</head>

<body>
Test: ????????????
</body>
</html>

Here, take a note of the third-last line: "Test: ????????????". In UTF-8, all special characters should be encoded with two bytes, but clearly, this was not the case. Something was doing the actual Unicode conversion twice. Initially, I thought this was the ASP.NET engine that was wrong, but after some research, I found this to be an incorrect assumption. Instead, what I found (when using a hex editor to view the files) that Dreamweaver had actually saved the files as UTF-8, but ASP.NET didn't correctly detect that the files were already in UTF-8 format, and instead worked with the files as if they were plain ANSI files. This caused the garbage characters to appear.

To fix the problem, I had to investigate Dreamweaver's settings. Under the Page Properties dialog box, I found the Title/Encoding section:

Here, the developers had forgot to check the "Include Unicode Signature (BOM)" tab, which means that Dreamweaver will save the file with the requested encoding, but will not include the so called "byte order mark" at the beginning of the file. See the Unicode FAQ for more details about UTF-8 encoding and BOMs.

When saved with a BOM, here's how the file looks like in a hex editor (Visual Studio 2005 for that matter):

As you can see, the file now starts with the byte sequence "EF BB BF", which is the standard BOM for UTF-8 encoded files. With this encoding, ASP.NET is able to return a correctly encoded file to the browser (here, telnet):

GET /test-utf8-bom.aspx HTTP/1.0

HTTP/1.1 200 OK
Connection: close
Date: Tue, 11 Jul 2006 09:01:34 GMT
Server: Microsoft-IIS/6.0
X-Developed-With: Delphi
P3P: CP="PHYo ONLo CONo TELo SAMo"
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 268

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>UTF-8 Test</title>
</head>

<body>
Test: ??????
</body>
</html>

The moral of the story is that even if Unicode is bliss in itself, it requires more skills to use it. It is a matter of a fact that plain ASCII was just simpler, though I don't regret the move, on the contrary.

Fri, 07 Jul 2006 14:05:20 GMT:
Why all spam ought to be Chinese :-)

Spam seems to be a fact of life, but unlike many of my friends and colleagues, I don't find it difficult to filter useful mail from junk. Also, lately the spam filters seem to have improved ("learned") a bit, which makes the life easier. However, another thing that makes my life easier is the so-called geopolitical shift towards East. In the beginning, Internet was English-only, but today Easter countries like China, Japan and other are growing to be the majority. This of course reflects the language of the junk mail.

Since I don't read Chinese for example, it is very easy to spot what I call the "Chinese spam” out of my normal mail. In fact, if all spam would be in such languages, it would make the life even easier. :-) As you see, I don't care much about mails that say things like "»¤s¸t¡@­º³¡"µL"½X"¼v¤ù¢°¢´¢´¢¯§K¹B¶OU" in the subject line.

Wed, 05 Jul 2006 13:51:37 GMT:
Calling the CPUID instruction from managed C# code

If you recall my earlier post from March regarding the CPUID instruction of Intel's x86 processors, I mentioned that you cannot call this instruction directly from C#. However, you can do this by using a native code (Win32 code) DLL that you simply call from C#. Here's how to do that briefly. What you need is Borland Delphi and Visual Studio 2005. I used Delphi version 2006 (Borland Developer Studio or BDS).

The first step is to create the library that you are going to call from C#. The code shown here is very similar to that in my March post.

library CPUID_InfoLib;

{$ALIGN 4}

{
Source:

"Intel Processor Identification and the CPUID Instruction"
- Application Note 485, January 2006.

http://developer.intel.com/
}

type
  ProcessorInfo = record
    MaximumBasicFunction    : cardinal;
    MaximumExtendedFunction : cardinal;
    VendorID                : array[0..12] of Char;
    Signature               : cardinal;
    SupportsMMX             : boolean;
    SupportsSSE             : boolean;
    SupportsSSE2            : boolean;
    SupportsSSE3            : boolean;
    SupportsHyperThreading  : boolean;
    SupportsIA64            : boolean;
    SupportsXDBit           : boolean;
    SupportsEMT64           : boolean;
  end;

var
  { globals used by the ReadProcessorInfo function }
  MBF,MEF     : cardinal;
  Sig         : cardinal;
  A,B,C       : cardinal;
  FF1,FF2,FF3 : cardinal;

function ReadProcessorInfo : ProcessorInfo; stdcall;
begin
  {$REGION 'cpuid'}
  asm
    { save registers used by the stdcall calling convention }
    push eax
    push ebx
    push ecx
    push edx
    { call CPUID }
    xor eax,eax
    cpuid
    mov MBF,eax
    { vendor ID }
    mov A,ebx
    mov B,edx
    mov C,ecx
    { signature & feature flags 1-2 }
    mov eax,1
    cpuid
    mov Sig,eax
    mov FF1,edx
    mov FF2,ecx
    { extended functions }
    mov eax,$8000000
    cpuid
    mov MEF,eax
    { feature flags 3 }
    mov eax,$8000001
    cpuid
    mov FF3,edx
    { restore }
    pop edx
    pop ecx
    pop ebx
    pop eax
  end;
  {$ENDREGION}
  {$REGION 'parse results'}
  Result.MaximumBasicFunction := MBF;
  Result.MaximumExtendedFunction := MEF;
  Result.Signature := Sig;
  Result.VendorID[0] := Chr((A and $000000FF) shr 0);
  Result.VendorID[1] := Chr((A and $0000FF00) shr 8);
  Result.VendorID[2] := Chr((A and $00FF0000) shr 16);
  Result.VendorID[3] := Chr((A and $FF000000) shr 24);

  Result.VendorID[4] := Chr((B and $000000FF) shr 0);
  Result.VendorID[5] := Chr((B and $0000FF00) shr 8);
  Result.VendorID[6] := Chr((B and $00FF0000) shr 16);
  Result.VendorID[7] := Chr((B and $FF000000) shr 24);

  Result.VendorID[8] := Chr((C and $000000FF) shr 0);
  Result.VendorID[9] := Chr((C and $0000FF00) shr 8);
  Result.VendorID[10] := Chr((C and $00FF0000) shr 16);
  Result.VendorID[11] := Chr((C and $FF000000) shr 24);
  Result.VendorID[12] := #0;
  {$ENDREGION}
  {$REGION 'flags'}
  Result.SupportsMMX := (FF1 and (1 shl 23)) <> 0;
  Result.SupportsSSE := (FF1 and (1 shl 25)) <> 0;
  Result.SupportsSSE2 := (FF1 and (1 shl 26)) <> 0;
  Result.SupportsSSE3 := (FF2 and (1 shl 0)) <> 0;
  Result.SupportsHyperThreading := (FF1 and (1 shl 28)) <> 0;
  Result.SupportsIA64 := (FF1 and (1 shl 30)) <> 0;
  Result.SupportsXDBit := (FF3 and (1 shl 20)) <> 0;
  Result.SupportsEMT64 := (FF3 and (1 shl 29)) <> 0;
  {$ENDREGION}
end;

exports
   ReadProcessorInfo;

begin
end.

Once you have this code compiled with Delphi, the result is a DLL file. The DLL exports a function that you can call. Now, start a new C# project and add the following code to it:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace Show_CPUID
{
    [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]
    public struct ProcessorInfo
    {
        public uint MaximumBasicFunction;
        public uint MaximumExtendedFunction;
        
        [MarshalAs(UnmanagedType.ByValTStr,SizeConst = 13)]
        public string VendorID;

        public uint Signature;

        [MarshalAs(UnmanagedType.I1)]
        public bool SupportsMMX;

        [MarshalAs(UnmanagedType.I1)]
        public bool SupportsSSE;

        [MarshalAs(UnmanagedType.I1)]
        public bool SupportsSSE2;

        [MarshalAs(UnmanagedType.I1)]
        public bool SupportsSSE3;

        [MarshalAs(UnmanagedType.I1)]
        public bool SupportsHyperThreading;

        [MarshalAs(UnmanagedType.I1)]
        public bool SupportsIA64;

        [MarshalAs(UnmanagedType.I1)]
        public bool SupportsXDBit;

        [MarshalAs(UnmanagedType.I1)]
        public bool SupportsEMT64;

        public string ToString()
        {
            string format = "MaximumBasicFunction = {0}\r\n" +
                "MaximumExtendedFunction = {1}\r\n" +
                "VendorID = \"{2}\"\r\n" +
                "Signature = {3}\r\n" +
                "SupportsMMX = {4}\r\n" +
                "SupportsSSE = {5}\r\n" +
                "SupportsSSE2 = {6}\r\n" +
                "SupportsSSE3 = {7}\r\n" +
                "SupportsHyperThreading = {8}\r\n" +
                "SupportsIA64 = {9}\r\n" +
                "SupportsXDBit = {10}\r\n" +
                "SupportsEMT64 = {11}\r\n";
            return string.Format(format, MaximumBasicFunction,
                MaximumExtendedFunction, VendorID, Signature,
                SupportsMMX, SupportsSSE, SupportsSSE2, SupportsSSE3,
                SupportsHyperThreading, SupportsIA64,
                SupportsXDBit, SupportsEMT64);
        }
    }

    public class CPUID_Info
    {
        [DllImport("CPUID_InfoLib.dll",CallingConvention=CallingConvention.StdCall)]
        public static extern void ReadProcessorInfo(ref ProcessorInfo pi);
    }
   
}

The idea is that the DLL returns a record (in Delphi speak) to the C# application, but you must let C# to know how to marshal the values correctly between Win32 and .NET. Similarly, you need to use a DllImport attribute to your managed code so that the compiler knows where to find the function to read the CPUID data. Here, the attribute specified the name of the DLL file and the calling convention (here, StdCall).

Finally, to call the function, all you need to do is:

ProcessorInfo pi = new ProcessorInfo();
CPUID_Info.ReadProcessorInfo(ref pi);
MessageBox.Show(pi.ToString());

There results are shown here:

Good luck!

Mon, 03 Jul 2006 14:16:44 GMT:
ADO.NET 3.0 and LINQ, fundamental changes ahead

If you've read this blog lately, you might have noted that I occasionally talk about LINQ, or Language Integrated Query. This is a new feature in the coming C# 3.0 language, which allows the developer to more intuitively access data in different data sources, including SQL databases (RDBMS).

Now, LINQ also requires updated to the ADO.NET framework, and MSDN has an article about this. Recommended reading for all C# developers, and why not Delphi developers as well. Only that Borland/DTG would get that .NET 2.0 support out even. :-)

Finally, happy 4th of July to all US readers!

Sun, 02 Jul 2006 18:04:55 GMT:
Where's threading going?

I don't often follow Intel's web site except during new processor launches, but lately they've improved their software developer site considerably (in my point of view, anyway), and this time I found an interesting article about threading.

The case is that according to Intel, threading will become the next obstacle for application developers. Today, applications still don't support threading as much they could, because developing such applications is often difficult, no matter if you use Win32 or .NET. However, in the future processors will become multicored, and so more and more of processor capacity will be wasted, unless applications can take advantage of the multiple cores. This Intel document is a good place to get started with the dilemma.

 

› Blog Archive