Live Fast, Code Hard, Die Young

Archive for the ‘Uncategorized’ Category

A new OS is born

Have you ever dreamed of creating your own operating system? Well, I guess not…Only a true masochist would come up with an idea like that. I mean, it’s 2008 now and we already have plenty of solid operating systems to choose among. Creating a new one would be just plain stupid…

Of course I couldn’t agree more, but for me it’s the ultimate challenge. I’ve been thinking about it for many years now so why not give it a shot? I really like to learn how things work under the hood. I understand it is a huge task and I admit that I certainly never will finish it. It will probably never even reach a state where it is usable to anyone, but at least for me it will be a very interesting learning experience.

So without further ado – welcome to the world PontOS!

Silly name?
Hey, what kind of a name is that? PontOS? Sounds incredibly silly…

Yes, I agree. I took that name because my OS is just silly! It’s a silly hobby project that doesn’t really do anything good (yet). Actually, a friend of mine joked about it and said something like "if you ever make your own OS it should be called PontOS!" In fact, it’s also a name of a Greek god of the sea and it was also better than the other lame suggestion I had…Pontux!

Background
Back in the early 90’s I wrote something similar to an OS for the Amiga. It was pretty simple by today’s standards but it had a simple memory manager, a custom track loader for floppy disk access along with its own file system handler and a simple debugger with disassembling functionality. It was used for taking over the machine completely when loading my demo for maximum performance (quite important on a 7.14MHz computer…).

After my Amiga years I jumped on the PC scene bandwagon and wrote plenty of demos and intros in assembler before I learned C and C++. Although it has been over ten years since I wrote my last line of assembler code, I still remember much of it and believe that it will help me out in this project. After all, writing kernel code is not for the faint of heart…

Foreground
Ok, now focus on the future and imagine the PontOS system. My goal for the first version is a very simple kernel. This will not be a multi purpose OS. I have a vision of a system that resembles the AmigaOS, with instant app switching and solid media performance. I hate when Windows starts swapping and thrashing the hard drive even on a 4GB RAM machine just to switch between two applications. It’s just so stupid. I want to try to write a more memory efficient system. It would also be awesome if I could use it from my living room couch as a media station…Hmm, yes I know, that’s far far in the future but at least I have a vision! For now I will be happy to just get a basic kernel up and running. Let’s see where this journey takes us…

Riding on the waves of inspiration!

Preserving transparency when converting icon to bitmap

Recently I wanted to show shell icons in a custom control on a Windows form. The custom control only supported bitmaps so I needed to convert the icons into bitmaps. This is quite easy in .NET since there is a nice Bitmap.FromHIcon() method. The problem is that when you use this method the icon transparency is lost, at least when you use it to extract shell icons (using the SHGetFileInfo API).
 
I tried to search for a solution but wasn’t able to locate any so I decided to fiddle around a bit on my own. Here is the way I came up with that works.
 

SHFILEINFO fi;

SHGetFileInfo(filename, 0, out fi, Marshal.SizeOf(typeof(SHFILEINFO)), FileInfoFlags.SHGFI_ICON | FileInfoFlags.SHGFI_SMALLICON);

using (Icon icon = Icon.FromHandle(fi.hIcon)) {

    Bitmap bm = new Bitmap(icon.Size.Width, icon.Size.Height);

    using (Graphics g = Graphics.FromImage(bm))

        g.DrawIcon(icon, 0, 0);

    return bm;

}

 

In other words, the solution is to draw the icon on an existing bitmap. The draw method will consider the transparency information when drawing which is what we want.
 
Here is the full class for retrieving a shell file icon as a bitmap:
 

public class FileInfoHelper {

 

    struct SHFILEINFO {

        public IntPtr hIcon;

        public int iIcon;

        public int dwAttributes;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]

        public string szDisplayName;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]

        public string szTypeName;

    }

 

    [Flags]

    enum FileInfoFlags : int {

        SHGFI_ICON = 0x000000100,    // get icon

        SHGFI_DISPLAYNAME = 0x000000200,    // get display name

        SHGFI_TYPENAME = 0x000000400,    // get type name

        SHGFI_ATTRIBUTES = 0x000000800,    // get attributes

        SHGFI_ICONLOCATION = 0x000001000,    // get icon location

        SHGFI_EXETYPE = 0x000002000,    // return exe type

        SHGFI_SYSICONINDEX = 0x000004000,    // get system icon index

        SHGFI_LINKOVERLAY = 0x000008000,    // put a link overlay on icon

        SHGFI_SELECTED = 0x000010000,    // show icon in selected state

        SHGFI_ATTR_SPECIFIED = 0x000020000,    // get only specified attributes

        SHGFI_LARGEICON = 0x000000000,    // get large icon

        SHGFI_SMALLICON = 0x000000001,    // get small icon

        SHGFI_OPENICON = 0x000000002,    // get open icon

        SHGFI_SHELLICONSIZE = 0x000000004,    // get shell size icon

        SHGFI_PIDL = 0x000000008,    // pszPath is a pidl

        SHGFI_USEFILEATTRIBUTES = 0x000000010,    // use passed dwFileAttribute

        SHGFI_ADDOVERLAYS = 0x000000020,    // apply the appropriate overlays

        SHGFI_OVERLAYINDEX = 0x000000040,    // Get the index of the overlay in

        // the upper 8 bits of the iIcon

    }

 

    [DllImport("shell32.dll", CharSet = CharSet.Auto)]

    static extern Int64 SHGetFileInfo(string pszPath, int dwFileAttributes, out SHFILEINFO psfi, int cbFileInfo, FileInfoFlags uFlags);

 

    /// <summary>

    /// Creates a new bitmap with the small icon for a file.

    /// </summary>

    /// <param name="filename"></param>

    /// <returns></returns>

    public static Bitmap GetFileIconAsBitmap(string filename) {

        SHFILEINFO fi;

        SHGetFileInfo(filename, 0, out fi, Marshal.SizeOf(typeof(SHFILEINFO)), FileInfoFlags.SHGFI_ICON | FileInfoFlags.SHGFI_SMALLICON);

        using (Icon icon = Icon.FromHandle(fi.hIcon)) {

            Bitmap bm = new Bitmap(icon.Size.Width, icon.Size.Height);

            using (Graphics g = Graphics.FromImage(bm))

                g.DrawIcon(icon, 0, 0);

            return bm;

        }

    }

}