Tuesday, February 07, 2006

In one of the comments to the post “Licensing classes in the SDF v2 (part 2)” a user asked a question about a way to tie up the license to the particular device and prevent coping licensed component or application between different user devices. This requirement would make the licensing process a little bit more complicated by adding a few more steps. It is driven by the fact that you will need to include the device id into the license key which later is signed with your private key. Evidently, you will have to add some code in your application that:


1. Will retrieve this device id (that's the easy part - just use the OpenNETCF.WindowsCE.DeviceManagement.GetDeviceid) and either automatically send it to your server or display it to the user.
2. Generate and sign the license that includes the device id with your private key.
3. Send this license to the user.
4. During validation of the license, retrieve the device id and include it into validation.

In order to utilize the Licensing library, you will need to create a new license provider by inheriting from the LicenseProvider class. Also you can either modify the .lic file by adding the DeviceID tag into the xml or append the device id to the contents of the .lic file during validation. If my schedule permits I'll try to add this implementation to the base library.

2/7/2006 2:11:21 PM (GMT Standard Time, UTC+00:00)  #     | 
 Thursday, February 02, 2006

Walter, the IE Program Manager, just announced on the IEBlog that the Windows RSS Platform is going to be available on the Windows XP as well as Vista. It will be installed as a part of IE7 package. This is indeed a great news and shows Microsoft's commitment to the “RSS anywhere” paradigm and would like to remind that they should not forget the Windows CE world. I am a strong believer that RSS has a great potential that is going to grow beyond Weblogs and news feed applications.

RSS
2/2/2006 6:35:14 PM (GMT Standard Time, UTC+00:00)  #    Comments [38]  | 
 Thursday, January 26, 2006

In my previous post I showed you the class diagram and the usage for the Licensing classes that are available as a part of SDF v2.

Today I'll explain a few other steps that you will be required to do in order to have licensing enabled in your application.

Attentive readers had probably noticed from looking at the class diagram that I have provided implementation of a concrete class PublicKeyLicenseProvider that inherits from the abstract LicenseProvider. The internal implementation of the PublicKeyLicenseProvider class is based on the asymmetric encryption such as RSACryptoServiceProvider. This was made possible by the fact that Microsoft has provided the implementation of the System.Security.Cryptography namespace to the CF v2.

Little bit of the background information on the asymmetric encryption. Asymmetric Encryption is a form of encryption where keys come in pairs. What one encrypts, only the other can decrypt. Asymmetric Encryption is also known as Public Key Cryptography, since users typically create a matching key pair, and make one public while keeping the other secret.

This fact has brought me to the idea of possibility to implement an almost fool proof system for licensing of components and applications in the CF v2. Even considering an "openness" of the .NET assemblies through the tools like Reflector, as long as your private key will stay unknown to a possible hacker, they will have a little chance to break the encryption.

And now after you have digested this information, you should be able to understand the other steps that are required:

1. You will have to generate a pair of the Public and Private keys. I have created a class LicenseKeyGenerator to help you with this task. Here's the CreateKeyPair method that you can use on either Windows CE or a desktop to generate these keys:

public static void CreateKeyPair( string path, int keySize )

{

      RSACryptoServiceProvider rsa = new RSACryptoServiceProvider( keySize );

      // Open the file stream for writing of the public key

      FileStream keyWriter = new FileStream(Path.Combine(path, "Pub.key"), FileMode.Create);

      // Get the key from provider

      byte[] key1 = rsa.ExportCspBlob(false);

      //Write it to the file

      keyWriter.Write(key1, 0, key1.Length);

      keyWriter.Close();

 

      // Open the file stream for writing of the private key

      keyWriter = new FileStream(Path.Combine(path, "Priv.key"), FileMode.Create);

      // Get the key from provider

      byte[] key2 = rsa.ExportCspBlob(true);

      //Write it to the file

      keyWriter.Write(key2, 0, key2.Length);

      keyWriter.Close();

}

2. Add the generated public key file Pub.key to the root (this is very important) of your project and set its Build Action to the Embedded Resource.

3. Add the LicenseProviderAttribute to your component as I had already shown to you in the previouse post.

4. Generate the license file based on the user data. The license is a simple XML file in the following format:

<licenseKey version="1.0">

    <product version="1.0.3.2489">NewControlproduct>

    <customerInfo>

        <Name>John DoeName>

        <Email>john.doe@mail.comEmail>

    customerInfo>

    <key>f4/WgB2JhgR9bQibFa6rbGDugM+4wqbyM/ES+6W17gxx+x//G9at5he3yT0wZGwk2okSAzqrRJoNfsakEDMlFg==key>

licenseKey>

 

The value of the key tag is the public key that we have generated in the previouse step. Here is the method Generate from the LicenseKeyGenerator class:

public void Generate(string publicKeyFile, string licenseFile)

{

      //Open public key file

      FileStream fs = new FileStream(licenseFile, FileMode.Open);

      BinaryReader keyReader = new BinaryReader(fs);

      // Create encryptor

      RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();

      rsaProvider.ImportCspBlob(keyReader.ReadBytes((int)keyReader.BaseStream.Length));

 

      // sign and save.

      this.Sign(rsaProvider);

      this.Save(licenseFile);

}

And you will use it like so:

private void cmdGenerate_Click(object sender, EventArgs e)

{

       // Create new license key.

       LicenseKeyGenerator licenseKey = new LicenseKeyGenerator();

       licenseKey.ProductName = txtProduct.Text;

       licenseKey.ProductVersion = txtVersion.Text;

       licenseKey.CustomerName = txtCustName.Text;

       licenseKey.CustomerEmail = txtCustEmail.Text;

 

       licenseKey.Generate((Application.ExecutablePath) + @"\Keys\Priv.Key", "MyCompany.NewControl.lic");

}

You can download the full version for the LicenseKeyGenerator class and a sample project from here:

GenLicense.zip (23.81 KB)

After you are done with these steps, the result is simple and effective - you've got a licensing system in place that would be rather hard to brake and easy to use.

1/26/2006 1:52:45 PM (GMT Standard Time, UTC+00:00)  #     | 
 Wednesday, January 25, 2006

The beta of the SDF v2.0 is available for download. We have worked really hard toward this release. Of course it fully supports the VS 2005 and CF v2. The SDF v2 also includes a lot of new functionality. Among those I would like to present to you the Licensing classes that I have developed. In the next few posts I will try to describe its design and show you how to actually use it.

The design of the Licensing functionality is based on the existing classes from the System.ComponentModel on the desktop like the Lisense, LicenseProvider, etc... Here is the class diagram representing the class structure of the Licensing library in the SDF v2:

So how would you use this library? The same way it is described in the MSDN documentation. Add the LicenseProviderAttibute to your component and use the LicenseManager to validate the license:

[LicenseProvider(typeof(PublicKeyLicenseProvider))]

public partial class NewControl : UserControl

{

     public NewControl()

   {

         InitializeComponent();

         

         if (!LicenseManager.IsValid(typeof(NewControl)))

         {

              MessageBox.Show("NewControl has invalid license");

         }

   }

 }

 

In the next post I'll explain to you which additonal steps are required to use the Licensing classes in your CF v2 application.

1/25/2006 4:47:00 PM (GMT Standard Time, UTC+00:00)  #    Comments [46]  | 
 Tuesday, January 17, 2006

The DateTimePicker control in the .NetCF v2 doesn't implement DropDown and CloseUp events which could be really helpful whe dealing with the picker. It doesn't mean that these events or messages are not available in the native counterpart. Win CE SDK docs show the presence of the DTN_CLOSEUP and DTN_DROPDOWN notification messages. It means that they are sent by the DateTime picker to its parent. So, I pulled the NativeWindow class to whip up the DateTimePickerEntender class that suclasses the form, catches the messages and raises the events to the client:

public class DateTimePickerExtender : NativeWindow

{

        public event System.EventHandler CloseUp;

        public event System.EventHandler DropDown;

 

        private IntPtr handle;

 

        public DateTimePickerExtender(IntPtr handle)

        {

            this.handle = handle;

            // Subclass the window

            this.AssignHandle(handle);

        }

 

        protected override void WndProc(ref Message m)

        {

            // Check for notification messages

            if (m.Msg == WM_NOTIFY)

            {

                NMHDR nmhdr = new NMHDR();

                        Marshal.PtrToStructure(m.LParam, nmhdr);

                switch (nmhdr.code)

                {

                    case DTN_DROPDOWN:       

                        // Raise the event

                        if (DropDown != null)

                            DropDown(this, new EventArgs());

                        break;

                    case DTN_CLOSEUP:

                        // Raise the event

                        if (CloseUp != null)

                            CloseUp(this, new EventArgs());

                        break;

                }

            }

            base.WndProc(ref m);

        }

 

 

        #region P/Invoke declarations

 

        private const int WM_NOTIFY = 0x004E;

 

        private const int DTN_FIRST = -760;

        private const int DTN_DROPDOWN = (DTN_FIRST + 6);

        private const int DTN_CLOSEUP = (DTN_FIRST + 7);

 

        private class NMHDR

        {

            public IntPtr hwndFrom = IntPtr.Zero;

            public uint idFrom = 0;

            public int code = 0; //uint

        }

 

        #endregion

}

Drop the DateTimePicker controls on the form, create and instance of the DateTimePickerExtender and hook up into the events:

DateTimePickerExtender dtEntender;

 

public Form1()

{

     InitializeComponent();

     dtEntender = new DateTimePickerExtender(this.Handle);

     dtEntender.CloseUp += new EventHandler(dtEntender_CloseUp);

     dtEntender.DropDown += new EventHandler(dtEntender_DropDown);

}

 

void dtEntender_DropDown(object sender, EventArgs e)

{

     Console.WriteLine("DropDown event");

}

 

void dtEntender_CloseUp(object sender, EventArgs e)

{

     Console.WriteLine("CloseUp event");

}

 

1/17/2006 7:35:53 PM (GMT Standard Time, UTC+00:00)  #     | 
 Thursday, January 05, 2006

Questions about embedding Macromedia Flash in CF application pop up from time to time on the CF NG. In fact it is very easy to do with Flash ActiveX for Pocket PC and WebBrowser control.

Here are five steps to achieve that:

1. Download and install Flash ActiveX for Pocket PC on your Pocket PC.

2. Create Smart Device and CF v2 project in VS 2005 and drop WebBrowser on your form.

3. Add flash file (.SWF) of your choice to your project and set its Built Action to content and “Copy if newer”

4. Create html file and make sure that you have a full path to the .SWF file in the src tag value:

<html>

<head>

<title>Dogshow Gametitle>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

head>

 

<body bgcolor="#FFFFFF" margintop=0 topmargin=0 leftmargin=0 marginleft=0>

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0" width="580" height="360">

  <param name=movie value="dogshow.swf">

  <param name=quality value=high>

  <embed src="file://\Program Files\MMediaClient\dogshow.swf" quality=high pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" type="application/x-shockwave-flash" width="580" height="360">

  embed>

 

object>

body>

html>

5. Make a call to the Navigate method with the name of your html file:

webBrowser1.Navigate(new Uri(@“file://\Program Files\MMediaClient\dogshow.htm“));

 

And enjoy the show:

1/5/2006 4:56:57 PM (GMT Standard Time, UTC+00:00)  #     | 
 Tuesday, January 03, 2006

You probably know how difficult it was to create a screen snapshot in CF v1. It required usage of many API calls and custom marshaling of a few structures. Just take a look at these resources:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetcomp/html/scibf.asp?frame=true

http://vault.netcf.tv/VaultService/VaultWeb/Blame.aspx?repid=2&path=%24%2fSDF%2fv1.4%2fOpenNETCF.Drawing%2fGDIPlus.cs&version=5&includedversions=20

The world has become a much better place since release of the CF v2 - availability of the native handles and ability to save image from Bitmap - have reduced the required code to just a few lines and one API call:

private void Snapshot(string filename, Graphics gx, Rectangle rect)

{

     Bitmap bmp = new Bitmap(rect.Width, rect.Height);

     // Create compatible graphics

     Graphics gxComp = Graphics.FromImage(bmp);

     // Blit the image data

     BitBlt(gxComp.GetHdc(), 0, 0, rect.Width, rect.Height, gx.GetHdc(), rect.Left, rect.Top, SRCCOPY);

     bmp.Save(filename, System.Drawing.Imaging.ImageFormat.Bmp);

     // Cleanup

     bmp.Dispose();

     gxComp.Dispose();

}

 

// P/Invoke declaration

[DllImport("coredll.dll")]

public static extern int BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, uint dwRop);

 

const int SRCCOPY = 0x00CC0020;

All you need to use it is just place the Snapshot method on your form and call it like that:

//Create a snapshot of a current view of the TextBox

Snapshot(@"\Temp\save.bmp", this.CreateGraphics(), textBox1.Bounds);

 

1/3/2006 1:44:08 PM (GMT Standard Time, UTC+00:00)  #     | 
 Wednesday, December 21, 2005