Search this site:


Check if datablase table exists

I am recently working with SQLite database and I was stuck with a very simple task: writing a function to create a table, existing table should be dropped. In other database engines this can be achieved using a simple CREATE OR REPLACE TABLE statement but this is not supported in current version of SQLite. Therefore I need to check the existence of a table before running the CREATE TABLE statement, but how?

Having a simple Google search, I got the clue at here: using the DbConnection.GetSchema() method.

Here is the complete code:

public static bool IsTableExists(SQLiteConnection conn, string table_name)
return conn.GetSchema("Tables").Select("Table_Name = '" + table_name + "'").Length > 0;

Since this is a method defined in ADO standard, so probably it will work for those ADO implementations of other database engine. (Not tested)


Win32 API Tracing Software

My friend has recommended a software to me for tracing Win32 API call of an executable. Seems that it can also track file and Registry access like Filemon and Regmon (or the Process Monitor) of Windows Sysinternals. Haven't tried it out yet, record here for future reference.



Compiling MudOS on Windows

I am compiling MudOS v22.2b14 on Windows... If you don't know what's a MudOS or a MUD, don't ask me and just let it be. Anyway, it is a nightmare compiling such old softwares...

First of all I don't have a VC6 now, neither can i find from MSDN subscriptions. I tried to compile all with VC.NET 2003, which has the most similar cl.exe with VC6.

After setting most of the stuff as suggested at here (page in Chinese, sorry). I still need to modify somethings manually. One of those are those related to bison. As I am using the GnuWin32 version, it seems to have little different behavior with the original one. Like it creates instead of XXXX_tab.c from XXXX.y. This is fixed by using the following command line instead:

bison make_func.y -o make_func_tab.c

Another problem with this GnuWin32 bison is a funny bugs. I got the following compile error when compiling edit_source.exe:
make_func_tab.c(929) : error C2449: found '{' at file scope (missing function header?)

Hey, a missing funtion header with code gerneted by bison....?! Having checking the code:
# if defined (__STDC__) || defined (__cplusplus)
int yyparse (void *YYPARSE_PARAM)
# else
int yyparse (YYPARSE_PARAM)
# endif
#else /* ! YYPARSE_PARAM */
#if defined (__STDC__) || defined (__cplusplus)
yyparse (void)
yyparse ()

What the... There is a suspcious semi-colon after the line of yyparse()... It may be the cause of the problem. However as I have just played with bison once or twice in one of my university course, I can't ensure my action is correct. So I have made a google search and found this thread. Oh, it was a old bug which has been already fixed in 2.3. Check the GnuWin32 bison version again, oops, it's 2.1... So I just removed the colon and compile again... and it seems to have done.

Now I am going to continue my compiling and wish me luck...!


Facebook Messages with links.... Don't trust them!

Yet another social engineering attack from those evil-minded guys...

Recently I've received messages like this from my friends through Facebook message:

Subject: i toook thiis viideo wwith you sielntly. wnana hvae smoe funn?
Another one:
Subject: Priivate ivdeo wtih you and yoour friennd. Who potsed it?

If you pay more attention, it is not hard to discover that the URL in the first message try to pretended to be owned by Google, and it's NOT Google. Google's URL is, NOT, or any other similar ones. Even the one with localized domain name should still get the .com (e.g., I was wrong. It seems to be really owned by Google. But look at the URL again, it actually indicated the URL is actually pointing to a page shared in Google Reader by other users, and the page may not be created by Google. So it's the same, there is nothing related to Google. The attacker just try to confuse you with the URL). The second URL is a bit cleverer, which make use of the "I'm feeling lucky" service provided by Google search. How do I know, the btnI parameter in the URL tells me this. The URL actually redirect you to the first search result if you search the terms "creating solutions for every need" (with quotes) in Google. It is ONLY the first search result returned by Google search but it is NOT from Google, and the page is UNTRUSTED!

I didn't click on the links yet (but to investigate, I will try to do so later when I have time), but my friends told me that after clicking the URL you will be prompted to install/upgrade your Flash player and a download dialogue of a EXE file will be displayed. After you run the EXE... BOOM! You are inflected and your friends will recieve similar messages like you do. (Huh, you don't think the virus are really from your friend, right...?)

Shame on them! I hate those guys abusing the trust between my friends and me. Let's be more careful to fight against such evil together! Here are what you can do:
  1. Don't open any URL inside Facebook messages, MSN messages, E-mails or whatever from anyone, including your best best best friend. Verify with them before if you really want to open it.
  2. Don't download and don't execute any EXE from untrusted website, especially when the site is opened by strange E-mails/messages/whatever.
  3. If you are unfortunately inflected, please post a message somewhere in your Facebook (wall, status message, notes or whatever), telling your dearest friends not to open the links in the messages sent by you if they have recieved any.
  4. Please kindly notify your friend who send you this message and warns her about this virus.
  5. Logout Facebook and another other online account when you finish using it, even if you are using your own private computer! Try not to remember password when using any online service.
  6. Spread this message in all the ways you can!

Yes, all these rules to protect yourself in the cyber world again. Simple but useful.

P.S. The real consequenes of opening those web pages and executed the virus may not be that simple. The real impact is still unknown. Will try to look into the issue if I have time.

Installing iGoogle Widget to Google Desktop

Just re-installed Google Desktop to my laptop for some purposes. I found that it is possible to add any iGoogle Gadgets to the Google Desktop Slide bar. Procedure is very simple: First browse to the Gidget page and copy the URL of the "View source" link, and paste to the "Add Gidget" search box in the Google Desktop application, press Enter and the Gadget will show up. Then you may add it like how you add any other Google Desktop Gadgets.

If you couldn't see any the Getget show up after pasting the links, please make sure the URL is in "http://XXXXXX/XXXX/XXXX.xml" format. You may also paste the URL into any browser to check if it is a valid XML document.

Have fun.


sudo and /etc/sudoers...

I have just done something very stupid...

I was connecting to a Mac OS X box in my office remotely and I tried to grant rights to certain users to run the sudo command. Here is what I did:

  1. sudo vi /etc/sudoers
  2. edit the file
  3. :wq (i.e. save and quite in vi)

Experienced users should be able to point out my stupid mistake here. Yes, I should never edit the sudoers file directly using an non-root user... Reason? It is really simple - what if I accidentally screw up the file?
$ sudo vi /etc/sudoers
>>> sudoers file: syntax error, line 23 <<<
sudo: parse error in /private/etc/sudoers near line 23

Just like this.


Yes. I have no way to fix the problem until I can get back to the office next Monday and boot the box into single-user mode.

Hurray! No more work this weekend!


Anyway, remember to use the visudo command to change the file, it can help to check the syntax before finalizing changes... Or at least I should su to root before editing this file, so that I don't need sudo to fix the sudo problem...

Note: this is not only applicable to Mac OS X but also other *-nix system too.

2008-09-29 Updated: I finally got back to office and boot the Mac into single-user mode. However, I need one more trick to update the files as the root filesystem is mounted at read-only by default. Here is the trick:
# mount -uw /


Google Chrome First Glance

Google has just released their new browser named Google Chrome today. Just tried it out. It seems to be notable faster for Google Maps, Google Documents and Picasa Web Ablum. Credits should goes to the new JS engine, and maybe also the individual process for each browser tab.

According to the official announcement:

We owe a great debt to many open source projects, and we're committed to continuing on their path. We've used components from Apple's WebKit and Mozilla's Firefox, among others -- and in that spirit, we are making all of our code open source as well. We hope to collaborate with the entire community to help drive the web forward.

Hurray. As expected, Google Chrome and Firefox are relatives. But sadly enough the Blogger WYSIWYG editor seems to be buggy in Google Chrome. My first unverified guess is that Apple's WebKit added codes to the box and mess things up... Stay claim, the browser is just in beta anyway.

See whether I have time to go more in-depth into the issue and try out other features of this new member of the web browser family.


SOLVED: Gmail Notifier does not work with the "Always use https" setting

I noticed that my Gmail Notifier always return the follow error in these few days:

An error has occurred.
Cannot connect to your mailbox.
Service temporarily unavailable

At first I suspected the relevant server was down but it's really strange that it lasted that long. There must be numerous complaints if it is really the case so I did a Google search using the above error.

Then I found the root cause. It is because I have enabled the "Always use https" setting in Gmail a few days ago. Oh my god, I do think this is a really good feature but I didn't expect it affect the handy notifier... Before having this setting I had to modify the URL to start with "https://" manually each time I was redirected out of the login page, which was quite inconvenient. So no way out, I have to gave up the notifier to enhance the security of my account. Wish Google will release a fix soon. Luckily Google has already released a patch to fix the issue. More details at here. Alternatively, you can choose to edit the Windows Registry yourself (caution needed!) to change the key HKEY_CURRENT_USER\Software\Google\Gmail\Flags\url to become You may need to restart your Gmail Notifier to let the change be effective.

Oh yes, I know that Google chat provide that feature too, but I just don't want to keep it running all the time.

More readings:
Gmail Help Discussion: Gmail Notifier not working
Gmail Notifier也抽风?


Adding GPS data into Images: comparison of software

Recently found one great comparison table of software synchronizing your photo with GPS track log. Here it is:
write GPS coordinates from tracklog into image


AdobeUpdater.exe error - ConnAPI.DLL not found

Recently encountered this error when launching Adobe reader:

Adobe Updater: AdobeUpdater.exe - Unable To Locate Component
This application has failed to start because ConnAPI.DLL was not found. Re-installing the application may fix this problem.

Had some Google search and read this KB article from Adobe, sound related but not exactly what I need. However, a great hint from it is that ConnAPI.DLL is something related to the Nokia PC Suit - I have that installed.

I found the file at C:\Program Files\PC Connectivity Solution, and I wonder why AdobeUpdater.exe couldn't. Thanks to the Filemon utility, I confirmed that AdobeUpdater.exe only searches for the file in folders defined in %PATH% environment variable, which is actually the default behavior when a program links a DLL.

So, the solution is simple: adding the location of ConnAPI.DLL back to the path:
C:\Program Files\PC Connectivity Solution

Problem solved. :)


Firefox 3 Download Day 2008 - Set a world record toegether!

Download Day

Let's set a Guinness World Record together by joining this Firefox 3 Download day event!!! Simply visit the site and pledge. You will received a reminder before the download day announced later.

Spread the news and spread Firefox!

2008-06-18 Updated:
It's NOW!!! Download Firefox 3 at the event official site or by 2008-06-18 17:0018:16 UTC to participate in the event!!!


SOLVED: Missing "Quick Edit" and "Edit Widget" icons in Blogger

Thanks to the help from wasted, the issue of "Quick Edit" icons mentioned was solved finally.

wasted has summarized the problem nicely and concisely that both of the followings have to be enabled for these icons to work (i.e. to load the authorization.css successfully):

  1. 3rd-party cookies
  2. HTTP Referer

Actually I did confirmed the 3rd-party cookies blocking was disabled in Firefox when I tested it before, while in IE the relevant settings are left default: "Override automatic cookie handling" is off. That's why I thought the problem wasn't there.

That means, referrer has to be the cause. I have to admit that I really missed this during my test, but according to my poor memory I didn't set anything relevant explicitly. And as what wasted say, since Opera is working on the same machine, those security software should not be related in this case (some of them removed the referrer in the header to protect privacy). To play safe, I double checked the option in my WebDeveloper Toolbar Firefox extension, oops... the "Disable Referrers" option is on! I don't know when it is turned on, but anyway, turning it off make the long-missed icons appear again! For those Firefox users who didn't install this extension may try to modify the configuration yourself. Steps are here:
  1. Type about:config in your Firefox location bar, and press Enter.
    (For Firefox 3 users, you may be prompted the following warning. No worry, just press "I'll be care, I promise!" is fine. Funny warning, ha...)

  2. Type "Referer" (single-R) in the filter bar, and you will then see a preference value named network.http.sendRefererHeader, set its value to 2. If the preference value does not exist, create one of integer type and set to 2.
  3. Reload your blog, and you will see those icons if you are logged in.
  4. You don't need to restart Firefox to reload this setting. But if there is no effect after changing the value, try to restart your Firefox.

So the problem only remains in IE now. Although I don't use IE frequently, my curiosity doesn't allow me to ignore the problem. I don't remember installing any plugins to IE or changing any relevant settings blocking HTTP referrer, and most importantly I can see the Referer header from IE while I was inspecting the network packets last time. If HTTP Referer is not the cause, 3rd-party cookies has to be. This implies the so called "automatic cookie handling" in IE7, unlike previous versions of IE, has blocked 3rd-party cookies somehow. This is actually a good move in terms of user's privacy but I have to say the interface is somehow misleading.

As you can see from the above screenshot, when the "Override automatic cookie handling" option is disabled, the radio box next to "Allow Third-party cookies" is filled. This gives users (at least me) a wrong implication that "automatic cookie handling" allows 3rd-party cookies by default...

Anyway, by overriding the behavior to allow 3rd-party cookies, and the icons are really out again. So all issues are solved now. Hurray!

A final note to add is that you can (and should) use an alternative way to allow the required cookies in IE7 without compromising your privacy. Instead of allowing 3rd-party cookies globally, add to the whitelist. To do so:
  1. Go to the Privacy tab in your Internet Options. Click the Sites button.
  2. Type "" in the Address of website field and then press the Allow button. Press OK twice to save the settings.
  3. Reload your blog. You will see those icons again if you have logged in.

Wish this article could help others who encounter simiar problems. Happy blogging!


Missing "Quick Edit" and "Edit Widget" icons in Blogger

Recently I have discovered the "Quick Edit" (i.e. ) and "Edit Widget" (i.e.. ) icons have gone.

I went to the Blogger Help Group to find some luck. Some threads did mention about similar syndromes but they are mostly related to a corrupted template. However, I have two blogs using different templates suffering from the same problem. It is unlikely to be my case. Resetting the widgets won't help.

I have actually done some analysis.

If you check the page with the DOM Inspector, or view its HTML source codes, you will find that those "Edit" icons are still there, with 3 classes defined: item-control, blog-admin and pid-XXXXXXX (some numbers). They are included in the page no matter who the visitor is, but by default they are hidden by embedded CSS generated by Blogger:

Quick Edit and Delete Comment Icons
----------------------------------------------- */

/* Hide it now, show it later with dynamically-generated CSS */
.item-control {

As mentioned in above CSS comment, those icons are shown using a dynamically generated CSS file. Inspecting the HTML source code, it is likely to be this one:

I sniffed the network packets while loading the page with Firefox 2/3 and IE 7 (other versions not tested) and find that the authorization.css returned has 1 bytes only, even if the visitor is the blog owner.

Funny enough, when accessing with Opera, the following content is returned:, { display:block; }, { display:inline; }

And yes, the icons can be shown without without any problem in Opera. Problem only occurs when using Firefox and IE. This further decreases the chances of a corrupted template.

So my guess is probably correct. Blogger really generates the authorization.css dynamically to display the icons. But for some reasons Blogger failed to returns the content to Firefox and IE, causing the icons to be disappeared.

Someone suggested that there should be something related to browser Cookies. Maybe and maybe not. I didn't check the Cookies content, but it's still strange that Cookies problem only occurs with using Firefox/IE but not Opera.

I have actually reported the issue at the group but received totally NONE response. Am I the only one suffer from it or no one cares about it? If you do meet similar problems, please post a reply to my thread to draw some attentions from those technical support.

It is really inconvenient to have those icons missing especially for careless people like me... Please bring them back soon!

2008-04-27 updates:
Problem is solved !




If you have ever used G-Archiver to archive/backup your Gmail data. Change your Google account password immediately before it is too late. The software was found sending user's login ID and passwords back to the author secretly without user's permission.

Read this post for details. I tried to verify the claim by downloading one version here (the official one is down). My anti-virus software prompted me for an Infostealer.Geemarc virus when I try to extract the zip file, and you may be interested in the advisory for the virus updated on 10th March 2008. Also checked out the scan result of the installer from VirusTotal. Seems that it's a quite well-know fact now and doesn't need any further verification anymore.

So, you can see how malicious programmers could hurt you now. Only trust those trustworthy please!


Recovering files from EXT3 filesystem

As you may already know, unlike EXT2, recovering deleted files from EXT3 used to be as hard as making use of data craving techniques on the raw data.

Here comes a good news. Carlo Wood has developed a EXT3 file (and directories too) recovery tool to recover his accidentally rm -rf deleted home directory containing 3GB of data, and he would like to share this useful tool with all of us. Up to my understanding, the tool make use of the journals to make this "impossible" task possible.

Don't hesitate to read his article for detailed explanation on the EXT3 filesystem and the recovery tool.


CAPTCHA Brusted!

The CAPTCHA of three popular free mail service provider were brusted recently (or not recently)!

Here are the detailed analysis from WebSense Security Labs, really worth reading:
Google's CAPTCHA busted in recent spammer tactics
Streamlined anti-CAPTCHA operations by spammers on Microsoft Windows Live Mail

I cannot find the analysis for Yahoo's, but here's the news article:
Yahoo's CAPTCHA Broken...Is a Spam Tsunami in the Offing?


Configuring Thunderbirds for Gmail IMAP

Today I opened Thunderbird on my Linux (I usually boot into Windows because of my job) and found that the profile was too out-of-dated that it still check my Gmail account via POP3. I have it reconfigured and planed to write a walk-through guide to share here. However, I found someone has already done so long ago, and has written exactly what I planed to, so I'd better not repeating again.

The official Gmail guide mentioned clearly the steps to make it works, and you may want to have some tweak to make it work better. Most of the settings are obvious in the graphical user interface, the only key point (may be) there is how to configure Thunderbird to use Gmail's original trash folder instead of creating an brand new [IMAP]\Trash label. Check out Ramesh's blog post for instructions. Just a point to add, indeed you don't need to edit the pref.js yourself, you may use the Config editor (about:config) instead:

  1. Go to Edit -> Preferences -> Advanced -> General -> Config Editor.
  2. You need to find out the server ID. You can type hostname in the filter box and look for in the values, and the server ID is part of the corresponding preference name (e.g. server9 if your the name is mail.server.server9.hostname).
  3. Then right click on the preference panel, create a new string (New -> String), enter mail.server.server#.trash_folder_name (# is the server ID you just found out) for name and [Gmail]\Trash for value.
  4. Close the Config editor and restart Thunderbird (you may need to restart a few times before the GUI reflects the changes). Done~

FYI, here is the official MozillaZine KB article for changing the trash folder in Thunderbird.

BTW, if you are configuring for your Google Apps email account, you may not be able to change the trash folder. I didn't investigate the reason behind, that's just my observation.


Some notes on C#.NET

Just some minor points to notes on C#.

1. The effective width or height of a control becomes zero when the control is docked.

That is, the Control.Height and Control.Width properties may return zero even it does occupy screen pixels. From my observation, there are some factors to this:
  • How the control itself is docked (Left, Right, Top, Bottom, or Fill)
  • How other control is docked
  • The situation only exists when the control has already been added to a control collection (Control.Controls)

You should be extremely careful if you have some how working with the control size if you have it docked. Take my situation as example, my form dynamically loads controls and resizes accordingly. The Control.SuspendLayout() and Control.ResumeLayout() methods are extremely useful in this case to avoid immediate changes of the size property:
= DockStyle.Fill;
this.Height += my_control.Height;

2. Special keys like Arrows, ESC and TAB do not fire KeyPress, KeyUp or KeyDown events

As title, Control.KeyPress, Control.KeyUp and Control.KeyDown do not help. To catch these key you need to override the Control.ProcessDialogKey() method.

protected override bool ProcessDialogKey(Keys keyData)
if (keyData == Keys.Escape)
return true;
return base.ProcessDialogKey (keyData);

BTW. All the above based on .NET Framework 1.1 that I am using. Newer versions may have different behavior.


Upgraded My Linux ATI Driver - AIGLX + COMPIZ Enabled!


Since the announcement for the Linux version of ATI display card driver supporting AIGLX last year, I don't have time to upgrade it. Until a few days ago, thanks to my illness, I got some time to give it a try. Having a brief Google search, I first followed the instructions here to remove the old driver, and then read here for hints to install the latest one. However, I made some stupid mistakes and failed to load the new driver module:

$ fglrxinfo
display: :0.0 screen: 0
OpenGL vendor string: Mesa project:
OpenGL renderer string: Mesa GLX Indirect
OpenGL version string: 1.4 (2.1 Mesa 7.0.1)

$ sudo modprobe fglrx
$ lsmod | grep fglrx
$ fglrxinfo
display: :0.0 screen: 0
OpenGL vendor string: Mesa project:
OpenGL renderer string: Mesa GLX Indirect
OpenGL version string: 1.4 (2.1 Mesa 7.0.1)


I raised this problem at the Ubuntu Forums (silly enough to reply to a wrong thread...) and the root cause was pinpointed very soon by DoDoNet, really Thanks! Disabling the old drivers in the Restricted Driver Manager probably add a line to blacklist the kernel module. Simply removing the line solves the problem.

To make the lives of Linux newbies (me included) easier, I decided to have a walk through of what I have done. First I'd like to talk about some backgrounds. Like many of you does, I enjoy the awesome desktop effects provided by Compiz Fusion. The display card of my Thinkpad T60 is an ATI Mobility Radeon X1400 which is not supported by the open source ATI display driver (at the time this article was written at least). But that's a pity that the old official ATI display driver has no AIGLX support. As a result, I need to run my Compiz Fusion over Xgl, which is relatively slow and need more resources. Owing to the high demand, AMD has finally add AIGLX support in their Linux version of driver, named fglrx. This means that ATI users can now running Compiz Fusion on their X directly with AIGLX, like those Nvidia users does long time ago.

Ah... I think it worth mentioning, my box is running Ubuntu Gutsy Gibbon.

Seems that I have already talked too much, so let's start now. The following instructions are based on Forlong's blog and the Community Ubuntu Documentation, plus some of my personal comments.

1. I removed my Xgl, also removed the xsession created for Xgl (you may not have those files):
$ sudo apt-get remove xserver-xgl
$ sudo rm /etc/X11/Xsession.d/98xserver-xgl_start-server
$ sudo rm /usr/share/xsessions/xgl.desktop

2. Then I went to System -> Administration -> Restricted Driver Manager to disable the ATI accelerated graphics driver. I also blacklisted it in the configuration file, using your favorite text editor to edit the following file:
$ sudo vim /etc/default/linux-restricted-modules-common

Add fglrx to the DISABLED_MODULES list (your list may contain more modules):

3. I rebooted the machine. Now it should be using the Mesa driver:
$ fglrxinfo
display: :0.0 screen: 0
OpenGL vendor string: Mesa project:
OpenGL renderer string: Mesa GLX Indirect
OpenGL version string: 1.4 (2.1 Mesa 7.0.1)


4. Then I installed pre-requisites for building the debs:
$ sudo apt-get install module-assistant build-essential fakeroot dh-make debhelper debconf libstdc++5 linux-headers-generic

5. I downloaded the latest driver from the official site, ran it to create debs. (Check the link to the latest driver for your card at here)
$ wget
$ chmod +x
$ sudo ./ --buildpkg Ubuntu/gutsy

6. Obviously, the next step was to install those debs.
$ sudo dpkg -i fglrx-kernel-source_8.455.2-0ubuntu1_i386.deb
$ sudo dpkg -i xorg-driver-fglrx_8.455.2-0ubuntu1_i386.deb

Optionally you can install the Catalyst Control Center too (I did):
$ sudo dpkg -i fglrx-amdcccle_8.455.2-0ubuntu1_i386.deb

7. I then enabled the driver in Xorg configuration by running the following command:
$ sudo aticonfig --initial

You may also edit /etc/X11/xorg.conf to customize your settings.

8. I rebooted my machine at this point, but if you do like I did, you may face the problem I mentioned earlier. Edit the following file with your favorite text editor before rebooting:
$ sudo vim /etc/modprobe.d/blacklist-restricted

Comment out or remove the line blacklist fglrx, if exists. Save the file and now you may reboot.

9. After your box is up again, check whether the module is loaded and whether the driver is in used:
$ lsmod | grep fglrx
fglrx 1476940 25
agpgart 35016 2 fglrx,intel_agp
$ fglrxinfo
display: :0.0 screen: 0
OpenGL vendor string: ATI Technologies Inc.
OpenGL renderer string: ATI Mobility Radeon X1400
OpenGL version string: 2.1.7281 Release


10. Yeah! What remaining is just to enable the lovely Compiz Fusion.
compiz --replace &

Everything should just work fine. Enjoy!

If you are tired of following the above steps manually, you may try the installation script prepared by DoDoNet, I found that when I asked my question at the Ubuntu Forums.

Wow, what a long long post... Wish it could help some of you.


Image Analysis

Image analysis has been a hot topic in digital forensics for a few years. Recently it goes out from the field to general public in HK after a sex sandal of a Hong Kong pop star. Professionals came out and tried to prove or disprove whether the photos are frauds.

So what's is image analysis? How are images analyzed? I am not an expert in this field, so I'd better leave these questions to those really professional. I've recent read a blog whose author is a speaker at the BlackHat conference, I guess you'd probably gain something from it like what I did.


C#: Determining whether a class implements certain interface

Sometimes it is useful to check whether a class (or its instance) implements certain interface. I found a good thread today discussing the issue:

How to determine base interface??? - .NET C#

If you are too busy (well, or too lazy) to dig the answer out of the long page, here is the solution:

The Type.IsAssignableFrom() method check whether a type can be assigned from another. It takes a System.Type object as argument, so if you are given a class or an instance of a class, you can use the typeof operator or the Object.GetType() method to get the corresponding System.Type object respectively. The MSDN has a clear definition of the returned value of the IsAssignableFrom() method:
Return Value
Type: System.Boolean

true if c and the current Type represent the same type, or if the current Type is in the inheritance hierarchy of c, or if the current Type is an interface that c implements, or if c is a generic type parameter and the current Type represents one of the constraints of c. false if none of these conditions are true, or if c is a null reference.
As you may have noticed, the IsAssignableForm() method can be applied to all System.Type object, so you can definitely use it to determine whether a class is derived (directly or indirectly) from another. But the case could be more complicated. When you have an interface and a class, the only possible relation is the class (or any class in its class hierarchy) implements the interface. But when you have two classes and try to find out their relation, one could be either the same as, the base or a derivative of another. For the first two case the IsAssignableForm() method returns a true value. Instead of explicitly checking whether two classes being the same, you may use the Type.isSubClassOf() method instead:

Let me use the following examples as a summary:
interface I { /* ... */ }

class A : I { /* ... */ }

class B : A { /* ... */ }

/* something */

typeof(A).isAssignableFrom(typeof(I))); // false
Console.WriteLine(typeof(A).isSubClassOf(typeof(I))); // false

typeof(I).isAssignableFrom(typeof(A))); // true
Console.WriteLine(typeof(I).isAssignableFrom(typeof(B))); // true
Console.WriteLine(typeof(B).isSubClassOf(typeof(I))); // false

typeof(A).isAssignableFrom(typeof(A))); // true
Console.WriteLine(typeof(A).isSubClassof(typeof(A))); // false

typeof(A).isAssignableFrom(typeof(B))); // true
Console.WriteLine(typeof(A).isSubClassof(typeof(B))); // false

typeof(B).isAssignableFrom(typeof(A))); // false
Console.WriteLine(typeof(B).isSubClassof(typeof(A))); // true

/* something else */


Posting codes in Blogger

I have just added some CSS modified from here (in Traditional Chinese) for to make codes looks better in Blogger.

/* .post-body is element in the template i am
currently using, you may want to replace it or
even remove it when applying to your site
.post-body code
: block; /* fixes a strange IE margin bug */
: "Courier New", "Monospace";
: 8pt;
: auto;
: #eee;
: 1px solid #ccc;
: 10px 10px 10px 21px;
: 300px;
: 100%;
: 1.2em;

Then, put all your codes between <pre><code> and </code></pre> tags. For examples:

The <code> tags is for CSS styling and the <pre> tag is for preserving white spaces, keeping the indentations. You may wonder why I do not use <pre> tag only, by giving it a class attribute and directly apply CSS style to it, like:
.post-body pre.code  {/* something here */}
and the block likes this:
<pre class="code">;</pre>

This should works too, but the reason I prefer the keeping the <code> tag is indeed simple: I would like to keep the semantic meaning for the content.

Just a reminder, you should also do the following replacement to avoid problems, note that the & has to be replaced first:
  • & to &amp;
  • < to &lt;
  • > to &gt;
If you use some code highlighter like the Actipro CodeHighlighter I am using, probably it will help you to handle the conversion too. You may find the service at here and here, it's free.


Implmentation of Singleton Pattern in C#

When you are talking about programming, a Singleton is a design pattern that address the problem of restricting only one single instance of a class. You can easily find implementations of the pattern from the web. Today when I was working on a programming tasks using C# .NET, I suddenly come up with an idea of having a generic purpose singleton. If you are using .NET Framework 2.0 or above, this can be easily achieved by using generics in C#. However, my program is still using .NET Framework 1.1 so I have to find other ways.

Thanks Chau for working it out with me, here is the solution we got:

public class Singleton
// hash table for storing the instances
private static System.Collections.Hashtable _instances = null;

// for thread safety
private static object MUTEX = new object();

// private to prevent instantiation of the class
private Singleton() { }

// overloaded method for convenience
public static object getInstance(System.Type type)
return getInstance(type, new object[0]);

// get an instance of specified type, the object array is the parameters to constructor
public static object getInstance(System.Type type, object[] parameters)
// initialize the internal hash table during the very first call
if (_instances == null)
= new Hashtable();

// just like ordinary implmentation of singleton, only creates new instance when
// there isn't one yet
if (!_instances.Contains(type))
// we need a list of type to get the ConstructorInfo object
System.Type[] types = new Type[parameters.Length];
for (int i=0; i&lt;parameters.Length; i++)
= parameters[i].GetType();

// the new instance is created by the following 3 lines of code
System.Reflection.ConstructorInfo constructor = type.GetConstructor(types);
object instance = Activator.CreateInstance(type);
constructor.Invoke(instance, parameters);

// store it for future use
_instances[type] = instance;

return _instances[type];

You can then use it like this:
SomeClass c = (SomeClass) Singleton.getInstance(typeof(SomeClass));

Someone may argue that this is not really a singleton, because one may still instantiate the class directly using its constructors. Strictly speaking yes. So this should only be a workaround, that to those classes can only be initiated once through this object. Maybe I really shouldn't name it a singleton... Anyway, please let it be until I got some other ideas.

Comments are welcome, thanks! Since the codes are simple and the main purpose is only to illustrate the idea, I would like to put it into the public domain, just use it freely if you find it useful. :)

Codes are highlighted by Actipro CodeHighlighter.

A software a day

This site lets you freely download licensed software everyday (legally), and each download only available for exactly 24 hours:

Giveaway of the day: free licensed software daily

Although you may not have heard of those software listed, but if you are geeks that keen on finding/testing useful software, this is a site for you. It could also be a great platform for software vendors to attract more users. Read here for more information.

Special notes:

  1. You need to install the software before the free download offer expires. It is because the version downloaded from there is inside a special container that verifies the Giveaway offer is still valid. Therefore, at least unpack from the special container once you downloaded the package.
  2. The softwares downloaded there usually have no free upgrade, no free technical support and is restricted to non-commercial use only.


Java: pass by reference or value?

Does Java pass function arguments by reference or value?

This is a confusing question. There are tons of people arguing this on the web. Here is my comment:

  • Java passes function arguments by value
  • Java handles object with object reference
So, when Java passes objects into function, it actually passes the object references. Object references is nothing special to other types, they are passed into function by values. That is, in short, Java passes object reference by value.

If you want to know more, read this very good article explaining the problem clearly with codes and graphical examples.


ERROR: Expansion ROM not initialized - PCI on Motherboard

Starting from yesterday I got the following messages when I boot up my Thinkpad T60:

Initializing Intel(R) Boot Agent GE v1.2.31

PXE-E05: The LAN adapter's configuation is corrupted or has not been initialized. The Boot Agent cannot continue.

After a while I got this:
Expansion ROM not initialized - PCI on Motherboard
Bus:00, Device:00, Function:00

Press [ESC] to continue

After I pressed ESC, everything looks normal, but there must be something goes wrong.

Having a search in Google, someone suggested to disable the internal network option ROM option in the BIOS, but this is obviously only a workaround. There is a discussion thread related to the issue, haven't read it yet.

Quite busy now, let me deal with it later.

2008-01-21 Updates:
Forget to mention, I have followed the instructions here: disabling the "Read Network ROM on Startup" under "Config/Networking" in the BIOS. Saved the settings and restarted, the message was gone, and the Ethernet card is still working. This should be just a workaround as I *thought* (yes, thought only) this setting was enabled since I get this notebook and got no problem. Has anyone contacted Lenovo support? What's their official explanation to the problem?