Click here to Skip to main content
6,597,576 members and growing! (21,373 online)
Email Password   helpLost your password?
Platforms, Frameworks & Libraries » Mobile Development » General     Intermediate

Generating GUIDs on the Pocket PC

By Microsoft - Compact Framework

Generating GUIDs on the Pocket PC
C#, VB, Windows, .NET CF, .NET, Mobile, Visual Studio, Dev
Posted:19 Jan 2004
Views:42,586
Bookmarked:29 times
Announcements
Loading...
 
Search    
Advanced Search
Add to IE Search
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
10 votes for this article.
Popularity: 4.37 Rating: 4.37 out of 5

1

2
1 vote, 10.0%
3
1 vote, 10.0%
4
8 votes, 80.0%
5

This article has been provided courtesy of MSDN.

Summary

The Guid.NewGuid method generates new GUIDs (globally unique identifier) but is not supported in the Microsoft .NET Compact Framework. Learn how to generate Guid objects that follow the documented GUID specifications for Pocket PC applications. (11 printed pages)

Contents

Overview

The .NET Compact Framework team constantly made tradeoffs between the framework footprint size, performance, and implementation time. The full .NET Framework Guid.NewGuid method calls the Windows API function CoCreateGuid that calls UuidCreate to generate globally unique 128-bit numbers. Unfortunately, these functions are not supported on the Pocket PC, so the Guid.NewGuid method was not implemented for the .NET Compact Framework.

It turns out that it's easy to write a custom implementation of the Guid.NewGuid method. The following shows a test application that generates GUIDs on the Pocket PC. It uses a custom class called PocketGuid, that uses the same algorithm as desktop GUIDs and is discussed in more detail later in this paper.

Figure 1. Generating GUIDs on the Pocket PC

The GUID Format

GUIDs consist of random numbers grouped into several sections: timestamp, clock sequence and node. The different sections for the GUID 8743428c-ef91-4d05-9e7c-4a2e856e813a are shown in the following table.

Table 1. Different sections of a GUID.

GUID Section Comments
8743428c Low field of the timestamp
ef91 Middle field of the timestamp
4d05 High field of the timestamp with multiplexed version number
9e High field of the clock sequence with multiplexed variant type
7c Low field of the clock sequence
4a2e856e813a Spatially unique node identifier

Variant

One to three bits of the clock sequence section are used to define the variant, or layout, of the GUID. Windows and the PocketGuid class generate variant type 2 GUIDs.

Table 2. Variant information stored in GUIDs

Upper 3 Bits of Clock Sequence Variant Type Comments
0 - - 0 Reserved for NCS (Network Computing System) backward compatibility
1 0 - 2 Standard format
1 1 0 6 Reserved for Microsoft Corporation backward compatibility
1 1 1 7 Reserved for future definition

Version

The upper four bits of the timestamp section contain the GUID's version that specifies the content of each section. Before Windows 2000, the CoCreateGuid function generated version 1 GUIDs. With Windows 2000, Microsoft switched to version 4 GUIDs, since embedding the MAC address was viewed as a security risk. The PocketGuid class also generates version 4 GUIDs.

Table 3. Version information stored in GUIDs

Upper 4 Bits of Timestamp Version Comments
0 0 0 1 1 Time-based version
Uses timestamp, clock sequence, and MAC network card address
0 0 1 0 2 Reserved
0 0 1 1 3 Name-based version
Constructs values from a name for all sections
0 1 0 0 4 Random version
Use random numbers for all sections

The following sites contain more information on the GUID specification:

Generating Random Numbers

The PocketGuid class uses the CryptGenRandom API function to generate random numbers. The first argument to the function is a CSP (cryptographic service provider) handle, that is created by calling CryptAcquireContext, and is released with the CryptReleaseContext function.

The CryptGenRandom function fills a buffer with cryptographically-random bytes that are more random (less predictable and more evenly distributed) than using the System.Random class. Entropy, the measure of uncertainty, is generated for the CryptGenRandom function from the following sources on Windows CE:

  • Thread and kernel switches
  • The current process identifier
  • The current thread identifier
  • Ticks since boot
  • Current time
  • Memory information
  • Object store statistics

The PocketGuid Class

Now that we know the GUID format (128 bit random number with multiplexed variant and version bits), and how to generate random numbers (use crypto API functions), it's very easy to implement the NewGuid method. The code for the PocketGuid class is shown below in C# and VB.NET.

The class contains two private enums, GuidVariant and GuidVersion, that list the different variant and version options. The private classes Const and WinApi contain constants used in the class and the DllImport statements for the crypto API functions. The static method PocketGuid.NewGuid does the following:

  • Calls CryptAcquireContext to get a crypto provider handle
  • Calls CryptGenRandom to generate a 128 bit cryptographically random number
  • Sets the variant and version bits
  • Creates a new System.Guid object and passes the byte array to the constructor
  • Calls CryptReleaseContext to release the crypto provider handle
  • Returns a new System.Guid object if successful, otherwise a SystemException is thrown

C#

using System;
using System.Runtime.InteropServices;

namespace PocketGuid
{
   /// <summary>

   /// Generate GUIDs on the .NET Compact Framework.

   /// </summary>

   public class PocketGuid
   {
      // guid variant types

      private enum GuidVariant
      {
         ReservedNCS = 0x00,
         Standard = 0x02,
         ReservedMicrosoft = 0x06,
         ReservedFuture = 0x07
      }

      // guid version types

      private enum GuidVersion
      {
         TimeBased = 0x01,
         Reserved = 0x02,
         NameBased = 0x03,
         Random = 0x04
      }
         
      // constants that are used in the class

      private class Const
      {
         // number of bytes in guid

         public const int ByteArraySize = 16;
         
         // multiplex variant info

         public const int VariantByte = 8;
         public const int VariantByteMask = 0x3f;
         public const int VariantByteShift = 6;

         // multiplex version info

         public const int VersionByte = 7;
         public const int VersionByteMask = 0x0f;
         public const int VersionByteShift = 4;
      }

      // imports for the crypto api functions

      private class WinApi
      {
         public const uint PROV_RSA_FULL = 1;
         public const uint CRYPT_VERIFYCONTEXT = 0xf0000000;

         [DllImport("coredll.dll")] 
         public static extern bool CryptAcquireContext(
            ref IntPtr phProv, string pszContainer, string pszProvider,
            uint dwProvType, uint dwFlags);

         [DllImport("coredll.dll")] 
         public static extern bool CryptReleaseContext( 
            IntPtr hProv, uint dwFlags);

         [DllImport("coredll.dll")] 
         public static extern bool CryptGenRandom(
            IntPtr hProv, int dwLen, byte[] pbBuffer);
      }
      
      // all static methods

      private PocketGuid()
      {
      }
      
      /// <summary>

      /// Return a new System.Guid object.

      /// </summary>

      public static Guid NewGuid()
      {
         IntPtr hCryptProv = IntPtr.Zero;
         Guid guid = Guid.Empty;
         
         try
         {
            // holds random bits for guid

            byte[] bits = new byte[Const.ByteArraySize];

            // get crypto provider handle

            if (!WinApi.CryptAcquireContext(ref hCryptProv, null, null, 
               WinApi.PROV_RSA_FULL, WinApi.CRYPT_VERIFYCONTEXT))
            {
               throw new SystemException(
               "Failed to acquire cryptography handle.");
            }
      
            // generate a 128 bit (16 byte) cryptographically random number

            if (!WinApi.CryptGenRandom(hCryptProv, bits.Length, bits))
            {
               throw new SystemException(
               "Failed to generate cryptography random bytes.");
            }
            
            // set the variant

            bits[Const.VariantByte] &= Const.VariantByteMask;
            bits[Const.VariantByte] |= 
               ((int)GuidVariant.Standard << Const.VariantByteShift);

            // set the version

            bits[Const.VersionByte] &= Const.VersionByteMask;
            bits[Const.VersionByte] |= 
               ((int)GuidVersion.Random << Const.VersionByteShift);
         
            // create the new System.Guid object

            guid = new Guid(bits);
         }
         finally
         {
            // release the crypto provider handle

            if (hCryptProv != IntPtr.Zero)
               WinApi.CryptReleaseContext(hCryptProv, 0);
         }
         
         return guid;
      }
   }
}

VB.NET

Imports System.Runtime.InteropServices

'

' Generate GUIDs on  the  .NET Compact Framework.

'

Public Class PocketGuid

   ' guid variant types

   Private Enum GuidVariant
      ReservedNCS = &H0
      Standard = &H2
      ReservedMicrosoft = &H6
      ReservedFuture = &H7
   End Enum

   ' guid version types

   Private Enum GuidVersion
      TimeBased = &H1
      Reserved = &H2
      NameBased = &H3
      Random = &H4
   End Enum

   ' constants  that are used in the class

   Private Class ConstValues
      ' number of  bytes in guid

      Public Const ByteArraySize As Integer = 16

      ' multiplex  variant  info

      Public Const VariantByte As Integer = 8
      Public Const VariantByteMask As Integer = &H3F
      Public Const VariantByteShift As Integer = 6

      ' multiplex  version  info

      Public Const VersionByte As Integer = 7
      Public Const VersionByteMask As Integer = &HF
      Public Const VersionByteShift As Integer = 4
   End Class

   ' imports for the crypto api functions

   Private Class WinApi
      Public Const PROV_RSA_FULL As Integer = 1
      Public Const CRYPT_VERIFYCONTEXT As Integer = &HF0000000

      <DllImport("coredll.dll")> _
      Public Shared Function CryptAcquireContext( _
         ByRef phProv As IntPtr, ByVal pszContainer As String, _
         ByVal pszProvider As String, ByVal dwProvType As Integer, _
         ByVal dwFlags As Integer) As Boolean
      End Function

      <DllImport("coredll.dll")> _
      Public Shared Function CryptReleaseContext( _
         ByVal hProv As IntPtr, ByVal dwFlags As Integer) As Boolean
      End Function

      <DllImport("coredll.dll")> _
      Public Shared Function CryptGenRandom( _
         ByVal hProv As IntPtr, ByVal dwLen As Integer, _
         ByVal pbBuffer() As Byte) As Boolean
      End Function
   End Class

   ' all static methods

   Private Sub New()
   End Sub

   ' Return a new System.Guid object.

   Public Shared Function NewGuid() As Guid
      Dim hCryptProv As IntPtr = IntPtr.Zero
      Dim guid As Guid = guid.Empty

      Try
         ' holds  random bits  for  guid

         Dim bits(ConstValues.ByteArraySize - 1) As Byte

         ' get crypto provider handle

         If Not WinApi.CryptAcquireContext(hCryptProv, Nothing, Nothing, _
            WinApi.PROV_RSA_FULL, WinApi.CRYPT_VERIFYCONTEXT) Then
            Throw New SystemException( _
               "Failed  to acquire cryptography  handle.")
         End If

         ' generate a 128 bit (16 byte) cryptographically random  number

         If Not WinApi.CryptGenRandom(hCryptProv, bits.Length, bits) Then
            Throw New SystemException( _
               "Failed  to generate  cryptography random  bytes.")
         End If

         ' set the variant

         bits(ConstValues.VariantByte) = bits(ConstValues.VariantByte) And _
            CByte(ConstValues.VariantByteMask)
         bits(ConstValues.VariantByte) = bits(ConstValues.VariantByte) Or _
            CByte(GuidVariant.Standard << ConstValues.VariantByteShift)

         ' set the version

         bits(ConstValues.VersionByte) = bits(ConstValues.VersionByte) And _
            CByte(ConstValues.VersionByteMask)
         bits(ConstValues.VersionByte) = bits(ConstValues.VersionByte) Or _
            CByte(GuidVersion.Random << ConstValues.VersionByteShift)

         ' create the new System.Guid object

         guid = New Guid(bits)
      Finally
         ' release the crypto provider handle

         If Not hCryptProv.Equals(IntPtr.Zero) Then
            WinApi.CryptReleaseContext(hCryptProv, 0)
         End If
      End Try

      Return guid
   End Function
End Class

GUID Trivia

Here are some GUID trivia questions you can use to impress your co-workers. You can run the PocketGuid test application or guidgen.exe on your desktop to check the questions; however, checking the last question might take a while.

  • Question: What is the only nibble (4 bits) that is always the same?
    • Answer: The 13th nibble specifies the GUID version and is always set to 4 for Windows 2000 and later. Example, 8743428c-ef91-4d05-9e7c-4a2e856e813a.
  • Question: What nibble only contains the values 8, 9, A, or B?
    • Answer: The 17th nibble contains the variant information so it will always be 8, 9, A or B since the upper bit is always set and next bit is always cleared. Example, 8743428c-ef91-4d05-9e7c-4a2e856e813a.
  • Question: How many GUID combinations are there?
    • Answer: There are 122 random bits (128 � 2 for variant - 4 for version) so this calculates to 2^122 or 5,316,911,983,139,663,491,615,228,241,121,400,000 possible combinations.

Links

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Microsoft - Compact Framework


Member

Location: United States United States

Other popular Mobile Development articles:

  • Writing Your Own GPS Applications: Part 2
    In part two of the series, the author of "GPS.NET" teaches developers how to write GPS applications suitable for the real world by mastering GPS precision concepts. Source code includes a working NMEA interpreter and sample high-precision application in C# and VB.NET.
  • Writing Your Own GPS Applications: Part I
    What is it that GPS applications need to be good enough to use for in-car navigation? Also, how does the process of interpreting GPS data actually work? In this three-part series, I will cover both topics and give you the skills you need to write a commercial-grade GPS application.
  • Learn How to Find GPS Location on Any SmartPhone, and Then Make it Relevant
    A step by step tutorial for getting GPS from any SmartPhone, even without GPS built in, and then making location useful.
  • iPhone UI in Windows Mobile
    It's an interface that works with transparency effects. As a sample I used an interface just like the iPhone one. In this tutorial I am explaining how simple is working with transparency on Windows Mobile.
  • Pocket 1945 - A C# .NET CF Shooter
    An article on Pocket PC game development
Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
  (Refresh) 
-- There are no messages in this forum --

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 19 Jan 2004
Editor: Smitha Vijayan
Copyright 2004 by Microsoft - Compact Framework
Everything else Copyright © CodeProject, 1999-2009
Web17 | Advertise on the Code Project