torsdag 23 maj 2013

A very simple webServer using .Net's HttpListener class

The other day a colleague and I ended up in the office kitchen discussing tiny web servers. Ha was writing some SDK code and wanted lightweight web server functionality in his code sample. I suggested using the HttpListener class which makes for great - and simple - web server implementations. I also had a vague memory of building something similar a year or so ago and I had a look in my personal code vault. Sure enough, there was indeed a lightweight web server implementation, though it had been somewhat de-simplified due to the nature of the app in which in resided. I decided to clean it up and hand it to him and after having failed to find any HttpListener sample code that was as clean as this I quickly decided to post it here as well.

Just a few short notes on the code.. It consists of an asynchronous and multithreaded webserver that can handle multiple simultaneous connections. The web server class (SimpleWebServer) has a Start() and a Stop() method that facilitates HttpListener- and thread management. It also exposes an event that is raised for each incoming request. The code itself is pretty self explanatory but here is a link to the MSDN documentation on the HttpListener Class.


class Program
{
  static void Main(string[] args)
  {
    var ws = new SimpleWebServer("http://localhost:666/Simple/");
    ws.RequestReceived += (sender, context) =>
      {
        var buffer = System.Text.Encoding.Default.GetBytes("Scattered I walk towards the fractured light. " + DateTime.Now);
        context.Response.OutputStream.Write(buffer, 0, buffer.Length);
        context.Response.StatusCode = (int)HttpStatusCode.OK;
        context.Response.OutputStream.Close();
      };
      ws.Start();
      Console.WriteLine("Listening to http://localhost:666/Simple/");
      Console.WriteLine("Press any key to stop...");
      Console.ReadLine();
      ws.Stop();
  }
}
class SimpleWebServer
{
  public delegate void RequestReceivedHandler(object sender, HttpListenerContext context);
  public event RequestReceivedHandler RequestReceived;

  private readonly HttpListener _listener;
  private bool _running;
  private readonly Thread _connthread;
  
  public SimpleWebServer(string prefix)
  {
    _listener = new HttpListener();
    _listener.Prefixes.Add(prefix);
    _connthread = new Thread(ConnectionThread);
  }
  
  public void Start()
  {
    _connthread.Start();
  }
  
  public void Stop()
  {
    _running = false;
    _listener.Stop();
  }
  
  private void ConnectionThread()
  {
    try
    {
      _running = true;
      _listener.Start();
      while (_running)
        ProcessRequest();
    }
    catch (HttpListenerException) { }
    catch (ThreadAbortException) { }
    catch (Exception) { }
  }

  private void ProcessRequest()
  {
    IAsyncResult result = _listener.BeginGetContext(ListenerCallback, _listener);
    result.AsyncWaitHandle.WaitOne();
  }

  protected void ListenerCallback(IAsyncResult result)
  {
    if (_listener == null || !_listener.IsListening) return;
    var context = _listener.EndGetContext(result);
    OnRequestReceived(context);
  }

  private void OnRequestReceived(HttpListenerContext context)
  {
    if (RequestReceived != null) RequestReceived(this, context);
  }
}

söndag 28 april 2013

HDR Exposure Fusion in C#

A year or so ago I fell in love with HDR photography after a friend of mine introduced the concept. Having taken a few HDR pictures myself there simply was no turning back.. Self-promoting here, but the one below is one of my own personal favorites.


I have a desperate need of understanding the world around me. HDR imaging is no difference and knowing this, my girlfriend (the wonderfully talented Security Pony at http://securitypony.com/) bought me a book about HDR imaging theory a few months back. It makes for great reading for anyone interested in the mechanics behind HDR. Having read the book, the next step was of course to build my own HDR image merge application. I settled on the Exposure Fusion algorithm by Tom Mertens that simply weights each pixel of each input image and then uses that weight to blend the images. There are other methods as well such as first merging to a 32bit HDR image and then use a tone mapper. 

I really recommend you to read Tom's paper on Exposure Fusion before looking at the code just to get a grasp on the algorithm. But, in short, here's what it does: 

By generating and combining saturation,- contrast- and 'well exposedness'-maps for every input image, weight maps of every image is created. The weight maps basically works as alpha masks and are used when blending the input images. Then, to avoid artifacts in the resulting image, the blending is done using the multi-resolution algorithm of Burt and Adelson as described in The Laplacian Pyramid as a Compact Image Code. And that's basically it. 

I've tried my best as to avoid third-party libraries so that it would be possible for the reader to debug and follow every step of the transformation process. The only library I used was one for bitmap encoding/decoding, used only for reading the input images and writing the resulting bitmap back to storage. The implication of this is that the source code contains a lot of general array manipulation functions that can be used for other purposes as well. Play around with it! :) 

Sample code: Here!

Ps. If you're interested in HDR photography I really recommend you to have a look at Trey Ratcliff's blog, Stuck in Customs.

söndag 9 december 2012

Implementing Huffman Coding in C# - Tutorial

Wow.. it's been a long time since I last published something here, but - at last - I'm back and this time I thought we'd take a deep dive into the world of Huffman.

For those new to Huffman Coding, here's a bit of background:
Huffman coding is an algorithm devised by David A. Huffman of MIT in 1952  for compressing text data to make a file occupy a smaller number of bytes. Albeit simple, this compression technique is powerful enough to have survived into modern time; variations of it is still in use in computer networks, modems, HDTV, and other areas.

I'm going to ignore various versions of Unicode here and for the sake of simplicity only focus on ASCII. I'm not lazy; I'm informative. :)
Normally text data is stored in a standard format of 8 bits per character - an octet. The idea of Hoffmann is to use different-length binary encodings for different characters. The more frequent the character, the fewer bits used. The trade-off is that some characters may need to use encodings that are longer than 8 bits, but this is reserved for characters that occur infrequently so the extra cost is worth it.

The steps involved in Huffman coding a given text source file into a destination compressed file are the following:

  1. Examine the source file's contents and count the occurrences of each character.
  2. Place each character and its frequency into a sorted priority queue. 
  3. Convert the contents of this priority queue into a binary tree. 
  4. Traverse the tree to discover the binary encoding of each character
  5. Re-examine the source file's contents, and for each character, output the encoded binary version of that character to the destination file. 
In this post, we are going to focus on step 2 through 4. For simplicity, we are going to output the binary encoding of each character in the form of a string instead of writing it to disc as a stream of bits. 

The files we will create are PriorityQueue.cs, HuffmannTree.cs, HuffannNode.cs and Program.cs.
PriorityQueue will be a simple - not thread safe! - implementation of a Priority Queue structure. .Net doesn't come with a priority queue built in so we're gonna build on a SortedDicitionary. More on that later.
HuffmanTree.cs will contain the actual logic for the Huffmann implementation. It exposes a constructor which takes a Dictionary that is the frequency mapping for each character. It also exposes Dictionary CreateEncodings() which creates the binary encoding for each character in the map. 
The HuffmanNode.cs will be a very basic tree node structure that keeps track of parent, childs, the character it represents and the character's frequency.

The text data we will work with are the string "ac bca ba z".
Step 1 would be to read the text data from file and map character and frequency but since we know the text data we also now the frequency of each character. Let's place them in a Dictionary in Program.cs.
IDictionary counts = new Dictionary<char, int>();

// ac bca ba z
counts.Add(' ', 3);
counts.Add('b', 2);
counts.Add('a', 3);
counts.Add('c', 2);
counts.Add('z', 1);
counts.Add('\n', 1);


Step 2 and 3 of the algorithm places these counts into binary tree nodes - HuffmanNode.cs. The nodes are put into a priority queue, which keeps them in sorted order with smaller counts at the front of the queue. Now the algorithm repeatedly removes two nodes from the front of the queue. A new node is created and the two nodes are set as children for the new node; the first node becomes the left child, and the second the right. The frequency variable of the new node is set to the accumulated value of the two nodes. i.e. if the frequency of node n1 was 5 and node n2 was 7 then the frequency of the new node is set to 12. The new node is then reinserted into the queue. This process is repeated until the queue contains only one node. This node is the root of the finished Huffman tree.

The Priority Queue structure is up next. A typical priority queue let's you enqueue an arbitrary set of objects, each if which are associated with a value or priority. In our case we will use integers as priority but you could basically use anything that's sortable. It then let's you dequeue one object at the time and it automatically makes sure that it's the item with the lowest priority that are dequeued.

using System.Collections.Generic;
using System.Linq;

namespace Huffman1
{
    internal class PriorityQueue<T>
    {
        private readonly SortedDictionary<int, Queue<T>> _sortedDictionary = new SortedDictionary<int, Queue<T>>();

        public int Count { get; private set; }

        public void Enqueue(T item, int priority)
        {
            ++Count;
            if (!_sortedDictionary.ContainsKey(priority)) _sortedDictionary[priority] = new Queue<T>();
            _sortedDictionary[priority].Enqueue(item);
        }

        public T Dequeue()
        {
            --Count;
            var item = _sortedDictionary.First();
            if (item.Value.Count == 1) _sortedDictionary.Remove(item.Key);
            return item.Value.Dequeue();
        }
    }
}
To be able to enter Huffman nodes into the priority queue we need the actual node.. 


// HuffmanNode.cs
namespace Huffman1
{
    internal class HuffmanNode
    {
        public HuffmanNode Parent { get; set; }
        public HuffmanNode Left { get; set; }
        public HuffmanNode Right { get; set; }
        public char Value { get; set; }
        public int Count { get; set; }
    }
}

< The code for inserting the character/frequence map into the priority queue and looping the queue to create a binary tree representation of the map is as follows:



private readonly HuffmanNode _root;

public HuffmanTree(IEnumerable<KeyValuePair<char, int>> counts)
{
    var priorityQueue = new PriorityQueue<HuffmanNode>();

    foreach(KeyValuePair<char, int> kvp in counts)
    {
        priorityQueue.Enqueue(new HuffmanNode {Value = kvp.Key, Count = kvp.Value}, kvp.Value);
    }

    while(priorityQueue.Count > 1)
    {
        HuffmanNode n1 = priorityQueue.Dequeue();
        HuffmanNode n2 = priorityQueue.Dequeue();
        var n3 = new HuffmanNode {Left = n1, Right = n2, Count = n1.Count + n2.Count};
        n1.Parent = n3;
        n2.Parent = n3;
        priorityQueue.Enqueue(n3, n3.Count);
    }

    _root = priorityQueue.Dequeue();
}

By now we have a tree and thus we can encode the binary tree Huffman-style. If you could see the tree it would look like this:


            12
           /  \
          /    \
         /      \
        /        \
       5          7
      / \        / \ 
     /   \      /   \
    /     \    /     \
   2      3   3      4
  / \    ' ' 'a'    / \
 1   1             2   2
'z''EOF'          'b' 'c'

EOF is a special character we use to keep track of where the string ended.
Step 4 of the algorithm traverses the tree to discover the binary encoding and by traversing the tree from the root ('12') down we can create a path from root to node. If we wanted to go to 'z' we would have to go "Left" three times where as if we wanted to go to 'a' we would take a right followed by left.

If we assign left and right with '0' and '1' respectively we can now construct a binary representation of the path. For example; our path to 'z' would be represented as '000' since we took left three times. Our path to 'a' would be represented as '10' and the path for 'b' would be '110'. By using the CreateEncodings() method of HoffmanTree.cs we can create a mapping for each character and binary path. This function won't serve more purpose than displaying that the tree has been built correctly and that we can traverse it but that's at least worth something. :) In it's entirety,  HoffmanTree.cs looks like this.


using System.Collections.Generic;

namespace Huffman1
{
    internal class HuffmanTree
    {
        private readonly HuffmanNode _root;

        public HuffmanTree(IEnumerable<KeyValuePair<char, int>> counts)
        {
            var priorityQueue = new PriorityQueue<HuffmanNode>();

            foreach(KeyValuePair<char, int> kvp in counts)
            {
                priorityQueue.Enqueue(new HuffmanNode {Value = kvp.Key, Count = kvp.Value}, kvp.Value);
            }

            while(priorityQueue.Count > 1)
            {
                HuffmanNode n1 = priorityQueue.Dequeue();
                HuffmanNode n2 = priorityQueue.Dequeue();
                var n3 = new HuffmanNode {Left = n1, Right = n2, Count = n1.Count + n2.Count};
                n1.Parent = n3;
                n2.Parent = n3;
                priorityQueue.Enqueue(n3, n3.Count);
            }

            _root = priorityQueue.Dequeue();
        }

        public IDictionary<char, string> CreateEncodings()
        {
            var encodings = new Dictionary<char, string>();
            Encode(_root, "", encodings);
            return encodings;
        }

        private void Encode(HuffmanNode node, string path, IDictionary<char, string> encodings)
        {
            if (node.Left != null)
            {
                Encode(node.Left, path + "0", encodings);
                Encode(node.Right, path + "1", encodings);
            } else
            {
                encodings.Add(node.Value, path);    
            }
        }
    }
}



If we were to write our text data to disc in compressed form we would introduce a new function in HuffmanTree.cs which would take the text data and an output stream for which to write to. For each character in the text data it would retrieve the binary encoding from the tree using the method described above and write the correlating bits to the output stream. To be able to read the compressed data we would need to store the state of the tree, but that is beyond the scope of Huffman and this tutorial. :) 

The complete listing for Program.cs is as follows

using System; using System.Collections.Generic; namespace Huffman1 { class Program { static void Main(string[] args) { IDictionary counts = new Dictionary<char, int>(); // ac bca ba z counts.Add(' ', 3); counts.Add('b', 2); counts.Add('a', 3); counts.Add('c', 2); counts.Add('z', 1); counts.Add('\n', 1); HuffmanTree tree = new HuffmanTree(counts); IDictionary<char, string> encodings = tree.CreateEncodings(); foreach (KeyValuePair<char, string> kvp in encodings) { Console.WriteLine((kvp.Key == '\n' ? "EOF" : kvp.Key.ToString()) + ":\t" + kvp.Value); } Console.ReadLine(); } } }
and that's about it. There are, of course, ways to improve performance but I wen't for readability here so I hope you'll forgive me. I hope you learned something new and, as always, you are free to use my code however you like.

torsdag 22 juli 2010

Solving Sudoku with Exact Cover

As many have already noted Sudoku can be described as an Exact Cover problem and can therefore be solved using Don Knuth's Algorithm X. Knuth himself has written an implementation of Algorithm X called Dancing Links which does just that.
For more information on Dancing Links, see Wikipedia.
A compact implementation of Algorithm X written in Python can be found here.

Altough there are many implementations of Algorithm X and Dancing Links out there I was yet to find an implementation written in CSharp. After spending more then enough time on Google, yet unable to find anything useful in written in CSharp, I decided to write it myself. My implementation of Dancing Links is based on thisimplementation written i Java. My implementation is tuned for solving Sudoku. Some parts of Algorithm X has been removed in order to boost performance but the code is probably still useful for anyone wanting to implement Algorithm X in CSharp.

I recommend reading the article associated with the Java-implementation as it contains a thorough description of the inner workings of Algorithm X, something which I won't provide here. I'm lazy. ;)

As a final note before we look at the code. The implementation is not only able to solve any given Sudoku puzzle. It's also capable of finding out exactly how many possible solutions are available. You could use this functionality to write a Sudoku puzzle-generator that is capable of generating puzzles for different skill levels.

The implementation is based on four classes.

Node.cs
Represents a node in the graph created by Algorithm X. Contains references to its neighbours, column and row and a label.

ColumnNode.cs
Inherits from Node and represents a column node.

DLArena
The actual Dancing Links implementation

DLSudoku
Support class that converts a Sudoku puzzle into a data structure that Algorithm X understands.

Complete code listing can be found here.

Solution requires Visual Studio 2008.

måndag 26 oktober 2009

Using the PowerState API

It's been a full week since my last post but I've been a bit busy writing sql scripts for an upcoming project at work.. But I did take a couple of minutes to write a simple Windows Mobile Powerstate API sample. Only two function calls are covered but together they hold the last bits you need to be able to write an application that "wakes" up the device at a set time and after performing various tasks are capable to return the device back to the previous state.

I'll show you how right now!

By now you already know how to use the notification library that comes with Windows Mobile. The problem with this API is that although capable of executing an application at a specific time it will not wake the device. In other words; you can initiate a thread but you won't be able to access peripheral devices such as the GPS receiver, open up an internet connection or send text messages. These are all things you often want to do when beeing able to execute applications on set times.
By applying a bit of PowerState magic this small issue may easily be solved.

First of you want to know the current power state of the device. This can easily be found out be calling GetSystemPowerState.

        [DllImport("coredll.dll", SetLastError = false)]
public static extern uint GetSystemPowerState(string sPowerStateName, uint iNameLen, ref uint Flags);

This function will return both the name of the current state as well as all the power state flags that has been set. Power state flags are a simple 32 bit bitmask. The header file declares the different power state flags as constants but I've choosen to declare them as a enum.

    public enum POWER_STATE
{
ON = 0x10000 // on state
, OFF = 0x20000 // no power, full off
, CRITICAL = 0x40000 // critical off
, BOOT = 0x80000 // boot state
, IDLE = 0x100000 // idle state
, SUSPEND = 0x200000 // suspend state
, UNATTENDED = 0x400000 // unattended state
, RESET = 0x800000 // reset state
, USERIDLE = 0x1000000 // user idle state
, BACKLIGHTON = 0x2000000 // device screen backlight on
, PASSWORD = 0x1000000 // this state is password protected
}


Calling GetSystemPowerState before applying a new power state allows you to save the current state and then re-apply it after you've done whatever it is you wanna do. SetSystemPowerState is just as easy to use as its equivelent Get-function.

        [DllImport("coredll.dll", SetLastError = false)]
public static extern uint SetSystemPowerState(string sPowerStatename, POWER_STATE nFlags, uint nForce);



You can pretty much ignore the PowerStateName parameter. nFlags speaks for itself and nForce can be used to force the device into a specific power state.

When using SetSystemPowerState to wake the device you basically call it passing POWER_STATE.ON as the nFlags parameter. And that's it..

I've written a small sample showing you how to use both function calls as well as how the POWER_STATE bitmask works. Enjoy!


            uint iRet;
uint nFlags = 0;
// This would be an excellent time to get aquinted with the StringBuilder object but
// let's do it the cheap way for now.
string sPowerStateName = " ";
iRet = WinCE.Powerstate.GetSystemPowerState(sPowerStateName, (uint)sPowerStateName.Length, ref nFlags);
if (iRet != 0)
{
MessageBox.Show("Failed to retrieve system power state");
return;
}
MessageBox.Show("Powerstate is: " + sPowerStateName);

bool IsOn = Convert.ToBoolean(nFlags & (uint)POWER_STATE.ON);
bool IsOff = Convert.ToBoolean(nFlags & (uint)POWER_STATE.OFF);
bool IsCritical = Convert.ToBoolean(nFlags & (uint)POWER_STATE.CRITICAL);
bool IsBoot = Convert.ToBoolean(nFlags & (uint)POWER_STATE.BOOT);
bool IsIdle = Convert.ToBoolean(nFlags & (uint)POWER_STATE.IDLE);
bool IsSuspended = Convert.ToBoolean(nFlags & (uint)POWER_STATE.SUSPEND);
bool IsUnattended= Convert.ToBoolean(nFlags & (uint)POWER_STATE.UNATTENDED);
bool IsReset = Convert.ToBoolean(nFlags & (uint)POWER_STATE.RESET);
bool IsUserIdle = Convert.ToBoolean(nFlags & (uint)POWER_STATE.USERIDLE);
bool IsBackLightOn = Convert.ToBoolean(nFlags & (uint)POWER_STATE.BACKLIGHTON);
bool IsPassword = Convert.ToBoolean(nFlags & (uint)POWER_STATE.PASSWORD);



            uint iRet;
iRet = WinCE.Powerstate.SetSystemPowerState(null, POWER_STATE.OFF, 1);
if (iRet == 0)
MessageBox.Show("Successfully set new power state");
else
MessageBox.Show("Failed to set new power state");

måndag 19 oktober 2009

Enumerate flash cards on a Windows Mobile based device

Today we'll have a look at how to enumerate available flash cards on a Windows Mobile based device using the native APIs FindFirstFlashCard and FindNextFlashCard. Code is written in C#.

To successfully enumerate the available flash cards, we will need to implement a couple of APIs using DllImport.


        [DllImport("coredll.dll", SetLastError = false)]
public static extern bool FindClose(IntPtr hFindFile);

[DllImport("note_prj.dll", SetLastError = false)]
public static extern IntPtr FindFirstFlashCard(byte[] bFindFlashData);

[DllImport("note_prj.dll", SetLastError = false)]
public static extern bool FindNextFlashCard(IntPtr hFlashCard, byte[] bFindFlashData);



We also need to enum some of the FILE_ATTRIBUTE_xxx values available in Winbase.h.


        public enum FILE_ATTRIBUTE
{
READONLY = 0x1
, HIDDEN = 0x2
, SYSTEM = 0x4
, DIRECTORY = 0x10
, ARCHIVE = 0x20
, INROM = 0x40
, NORMAL = 0x80
, TEMPORARY = 0x100
, SPARSE_FILE = 0x200
, REPARSE_POINT = 0x400
, COMPRESSED = 0x800
, ROMSTATICREF = 0x1000
, ROMMODULE = 0x2000
, ENCRYPTED = 0x4000
}



Next, we need to implement the WIN32_FIND_DATA structure. As you can see in our import of FindFirstFlashCard we don't actually pass an instance of the win32_find_data structure to the API, but instead we pass a byte buffer that are later converted to a win32_find_data structure. I've added a couple of properties to the structure to make working with file attributes a bit more .Net-ish. As you can see, the byte-to-structure-code is located in the constructur the same way as we did with the notification structures last week.


        [StructLayout(LayoutKind.Sequential)]
public class WIN32_FIND_DATA
{
public uint FileAttributes;
private FILETIME ftCreationTime;
private FILETIME ftLastAccessTime;
private FILETIME ftLastWriteTime;
public DateTime dtCreationTime;
public DateTime dtLastAccessTime;
public DateTime dtLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwOID;
public string FileName;
public bool IsReadOnly;
public bool IsHidden;
public bool IsSystem;
public bool IsDirectory;
public bool IsArchive;
public bool IsInRom;
public bool IsNormal;
public bool IsTemporary;
public bool IsSparseFile;
public bool HasReparsePoint;
public bool IsCompressed;
public bool HasRomStaticRef;
public bool IsRomModule;
public bool IsEncrypted;

public WIN32_FIND_DATA()
{
}
public WIN32_FIND_DATA(byte[] Buf, uint Size)
{
int Index = 0;
int iEndOfString = 0;
System.Text.UnicodeEncoding enc = new UnicodeEncoding();
this.FileAttributes = BitConverter.ToUInt32(Buf, Index);
Index += 4;
this.ftCreationTime.dwLowDateTime = BitConverter.ToUInt32(Buf, Index);
Index += 4;
this.ftCreationTime.dwHighDateTime = BitConverter.ToUInt32(Buf, Index);
Index += 4;
this.ftLastAccessTime.dwLowDateTime = BitConverter.ToUInt32(Buf, Index);
Index += 4;
this.ftLastAccessTime.dwHighDateTime = BitConverter.ToUInt32(Buf, Index);
Index += 4;
this.ftLastWriteTime.dwLowDateTime = BitConverter.ToUInt32(Buf, Index);
Index += 4;
this.ftCreationTime.dwHighDateTime = BitConverter.ToUInt32(Buf, Index);
Index += 4;
this.nFileSizeHigh = BitConverter.ToUInt32(Buf, Index);
Index += 4;
this.nFileSizeLow = BitConverter.ToUInt32(Buf, Index);
Index += 4;
this.dwOID = BitConverter.ToUInt32(Buf, Index);
Index += 4;

iEndOfString = WinCE.findEndOfString(Buf, Index, (int)Size);
this.FileName = enc.GetString(Buf, Index, iEndOfString - Index - 2);
Index = iEndOfString;

this.IsReadOnly = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.READONLY);
this.IsHidden = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.HIDDEN);
this.IsSystem = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.SYSTEM);
this.IsDirectory = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.DIRECTORY);
this.IsArchive = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.ARCHIVE);
this.IsInRom = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.INROM);
this.IsNormal = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.NORMAL);
this.IsTemporary = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.TEMPORARY);
this.IsSparseFile = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.SPARSE_FILE);
this.HasReparsePoint = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.REPARSE_POINT);
this.IsCompressed = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.COMPRESSED);
this.HasRomStaticRef = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.ROMSTATICREF);
this.IsRomModule = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.ROMMODULE);
this.IsEncrypted = Convert.ToBoolean(this.FileAttributes & (uint)FILE_ATTRIBUTE.ENCRYPTED);

this.dtCreationTime = DateTime.FromFileTime(this.ftCreationTime.GetAsLong());
this.dtLastAccessTime = DateTime.FromFileTime(this.ftLastAccessTime.GetAsLong());
this.dtLastWriteTime = DateTime.FromFileTime(this.ftLastWriteTime.GetAsLong());
}
}



Now that's a lot of code!
The win32_find_data structure has a couple of instances of the FILETIME structure. This is a simple structure consisting of just two 32 bit unsigned integer values and a function that returns a 64 bit unsigned integer.


    [StructLayout(LayoutKind.Sequential)]
public struct FILETIME
{
public uint dwLowDateTime;
public uint dwHighDateTime;
public long GetAsLong()
{
long lRet;
lRet = dwHighDateTime;
lRet = lRet << 32;
lRet = dwLowDateTime;
return lRet;
}
}


Returning the filetime structure as a 64 bit integer value makes it possible for us to directly convert it to a .Net DateTime structure using the static DateTime.GetFromFileTime(long lFileTime) function.


this.dtCreationTime = DateTime.FromFileTime(this.ftCreationTime.GetAsLong());


Next up is a simple function that enumerates all flash cards and outputs the path using System.Diagnostics.Trace.WriteLine(string sVal).


            FileSystem.WIN32_FIND_DATA FindData;
Byte[] Buf = new byte[295]; // Struct is 40 bytes + MAX_PATH (255 bytes) = 295 bytes

IntPtr hFlashCard = WinCE.FileSystem.FileAppMgmt.FindFirstFlashCard(Buf);

if (hFlashCard != IntPtr.Zero)
{
FindData = new FileSystem.WIN32_FIND_DATA(Buf, 295);
System.Diagnostics.Trace.WriteLine("Filename:" + FindData.FileName);
Buf = new byte[295];

while (WinCE.FileSystem.FileAppMgmt.FindNextFlashCard(hFlashCard, Buf))
{
FindData = new FileSystem.WIN32_FIND_DATA(Buf, 295);
System.Diagnostics.Trace.WriteLine("Filename:" + FindData.FileName);
}
WinCE.FileSystem.FindClose(hFlashCard);
System.Diagnostics.Trace.WriteLine("Succeeded");
}
else
{
System.Diagnostics.Trace.WriteLine("Failed");
}




And that's about it.. Check back tomorrow when we look closer on a couple other file system related APIs.

torsdag 15 oktober 2009

CeGetUserNotification

The last notification related API that we will look at for this time is CeGetUserNotification. As its name implies this function returns information on a previously created notification. The function takes a notification handle as input and returns a byte array containing an instance of a CE_NOTIFICATION_INFO_HEADER. This structure points to two other structures that are allocated in the same buffer, CE_NOTIFICATION_TRIGGER and CE_USER_NOTIFICATION.

        [DllImport("CoreDLL.dll", SetLastError = false, EntryPoint="CeGetUserNotification")]
public static extern bool GetUserNotification(IntPtr hNotification, uint BufferSize, out uint BytesNeeded, byte[] Buffer);


Calling GetUserNotification passing null values and a valid notification handle will return the bytes needed for the byte buffer. You then call GetUserNotification once more passing both a notification handle as well as a byte buffer.
    GetUserNotification(hNotification, 0, out Size, null);
Buf = new byte[Size];
GetUserNotification(hNotification, Size, out Size, Buf)


Had we been doing this in c++ then casting the byte array into a CE_NOTIFICATION_INFO_HEADER would be as easy as 1-2-3.. Casting this C-style array using CSharp is quite but not quite as easy. Basically we have to read the buffer byte by byte, using the data to set the values of an instance of the structure. I choose to do this using the structures constructor. My implementation of CE_NOTIFICATION_INFO_HEADER is found below.


[StructLayout(LayoutKind.Sequential)]
public class CE_NOTIFICATION_INFO_HEADER
{
[MarshalAs(UnmanagedType.U4)]
public uint hNotification;
[MarshalAs(UnmanagedType.U4)]
public uint dwStatus;
public CE_NOTIFICATION_TRIGGER cent;
public CE_USER_NOTIFICATION ceun;

public CE_NOTIFICATION_INFO_HEADER(byte[] Buf, uint Size)
{
int Index = 0;
try
{
this.hNotification = BitConverter.ToUInt32(Buf, Index);
Index += 4;
this.dwStatus = BitConverter.ToUInt32(Buf, Index);
Index += 4;
uint pcent = BitConverter.ToUInt32(Buf, Index);
Index += 4;
uint pceun = BitConverter.ToUInt32(Buf, Index);
Index += 4;
if (pcent > 0 && Buf[Index] == Marshal.SizeOf(new CE_NOTIFICATION_TRIGGER()))
this.cent = new CE_NOTIFICATION_TRIGGER(Buf, Size, ref Index);
if (pceun > 0)
this.ceun = new CE_USER_NOTIFICATION(Buf, Size, ref Index);
}
catch (Exception ex)
{
throw ex;
}
}
}

As you can see I've overloaded the constructors of both CE_NOTIFICATION_TRIGGER and CE_USER_NOTIFICATION to be able to create instances from a byte array. Here are the final implementations of both structures.


[StructLayout(LayoutKind.Sequential)]
public class CE_NOTIFICATION_TRIGGER
{
public UInt32 Size = 0;
[MarshalAs(UnmanagedType.U4)]
public CeNotificationType Type;
[MarshalAs(UnmanagedType.U4)]
public CeNotificationEvent Event;
[MarshalAs(UnmanagedType.LPWStr)]
public string pApplication;
[MarshalAs(UnmanagedType.LPWStr)]
public string pArgs;
public SYSTEMTIME StartTime;
public SYSTEMTIME EndTime;
public CE_NOTIFICATION_TRIGGER()
{
}

public CE_NOTIFICATION_TRIGGER(byte[] Buf, uint Size, ref int Index)
{
int iEndOfString;
System.Text.UnicodeEncoding enc = new UnicodeEncoding();
uint lpszApp = 0;
uint lpszArgs = 0;
this.Size = BitConverter.ToUInt32(Buf, Index);
Index += 4;
this.Type = (CeNotificationType)BitConverter.ToUInt32(Buf, Index);
Index += 4;
this.Event = (CeNotificationEvent)BitConverter.ToUInt32(Buf, Index);
Index += 4;
lpszApp = BitConverter.ToUInt32(Buf, Index);
Index += 4;
lpszArgs = BitConverter.ToUInt32(Buf, Index);
Index += 4;
this.StartTime = new SYSTEMTIME(Buf, Index);
Index += 16;
this.EndTime = new SYSTEMTIME(Buf, Index);
Index += 16;
if (lpszApp > 0)
{
iEndOfString = WinCE.WinCE.findEndOfString(Buf, Index, (int)Size);
this.pApplication = enc.GetString(Buf, Index, iEndOfString - Index - 2);
Index = iEndOfString;
}
if (lpszArgs > 0)
{
iEndOfString = WinCE.WinCE.findEndOfString(Buf, Index, (int)Size);
this.pArgs = enc.GetString(Buf, Index, iEndOfString - Index - 2); // Stupid solution to double null ending..
Index = iEndOfString;
}
}
}

[StructLayout(LayoutKind.Sequential)]
public class CE_USER_NOTIFICATION
{
[MarshalAs(UnmanagedType.U4)]
public PUN_FLAGS ActionFlags;
[MarshalAs(UnmanagedType.LPTStr)]
public string sDialogTitle;
[MarshalAs(UnmanagedType.LPTStr)]
public string sDialogText;
[MarshalAs(UnmanagedType.LPTStr)]
public string sSound;
[MarshalAs(UnmanagedType.U4)]
public uint nMaxSound;
[MarshalAs(UnmanagedType.U4)]
public uint Reserved;
public CE_USER_NOTIFICATION()
{
}

public CE_USER_NOTIFICATION(byte[] Buf, uint Size, ref int Index)
{
int iEndOfString;
System.Text.UnicodeEncoding enc = new UnicodeEncoding();

this.ActionFlags = (PUN_FLAGS)BitConverter.ToUInt32(Buf, Index);
Index += 4;
uint lpszDialogTitle = BitConverter.ToUInt32(Buf, Index);
Index += 4;
uint lpszDialogText = BitConverter.ToUInt32(Buf, Index);
Index += 4;
uint lpszSound = BitConverter.ToUInt32(Buf, Index);
Index += 4;
this.nMaxSound = BitConverter.ToUInt32(Buf, Index);
Index += 4;
// read Reserved
Index += 4;
if (lpszDialogTitle > 0)
{
iEndOfString = WinCE.WinCE.findEndOfString(Buf, Index, (int)Size);
this.sDialogTitle = enc.GetString(Buf, Index, iEndOfString - Index - 2);
Index = iEndOfString;
}
if (lpszDialogText > 0)
{
iEndOfString = WinCE.WinCE.findEndOfString(Buf, Index, (int)Size);
this.sDialogText = enc.GetString(Buf, Index, iEndOfString - Index - 2);
Index = iEndOfString;
}
if (lpszSound > 0)
{
iEndOfString = WinCE.WinCE.findEndOfString(Buf, Index, (int)Size);
this.sSound = enc.GetString(Buf, Index, iEndOfString - Index - 2);
Index = iEndOfString;
}
}
}
Creating an instance of a CE_NOTIFICATION_INFO_HEADER from a byte array can now be accomplished like this:
    CE_NOTIFICATION_INFO_HEADER cenih = new Notify.CE_NOTIFICATION_INFO_HEADER(Buf, Size);

And there you have it.. You now have all the pieces needed to implement notifications and scheduled events in your .Net applications. You also have all the pieces needed to create an application that manages all OS specific and user created notifications.

I wont post anything tomorrow, friday, but I'll be back monday. Have a nice weekend!