PocketGuid

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 SectionComments
8743428cLow field of the timestamp
ef91Middle field of the timestamp
4d05High field of the timestamp with multiplexed version number
9eHigh field of the clock sequence with multiplexed variant type
7cLow field of the clock sequence
4a2e856e813aSpatially 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 SequenceVariant TypeComments
0 - -0Reserved for NCS (Network Computing System) backward compatibility
1 0 -2Standard format
1 1 06Reserved for Microsoft Corporation backward compatibility
1 1 17Reserved 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 TimestampVersionComments
0 0 0 11Time-based version
Uses timestamp, clock sequence, and MAC network card address
0 0 1 02Reserved
0 0 1 13Name-based version
Constructs values from a name for all sections
0 1 0 04Random 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#

Collapse
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

Collapse
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



Location: United States United States
内容概要:本文深入探讨了金属氢化物(MH)储氢系统在燃料电池汽车中的应用,通过建立吸收/释放氢气的动态模型和热交换模型,结合实验测试分析了不同反应条件下的性能表现。研究表明,低温环境有利于氢气吸收,高温则促进氢气释放;提高氢气流速和降低储氢材料体积分数能提升系统效率。论文还详细介绍了换热系统结构、动态性能数学模型、吸放氢特性仿真分析、热交换系统优化设计、系统控制策略优化以及工程验证与误差分析。此外,通过三维动态建模、换热结构对比分析、系统级性能优化等手段,进一步验证了金属氢化物储氢系统的关键性能特征,并提出了具体的优化设计方案。 适用人群:从事氢能技术研发的科研人员、工程师及相关领域的研究生。 使用场景及目标:①为储氢罐热管理设计提供理论依据;②推动车载储氢技术的发展;③为金属氢化物储氢系统的工程应用提供量化依据;④优化储氢系统的操作参数和结构设计。 其他说明:该研究不仅通过建模仿真全面验证了论文实验结论,还提出了具体的操作参数优化建议,如吸氢阶段维持25-30°C,氢气流速0.012g/s;放氢阶段快速升温至70-75°C,水速18-20g/min。同时,文章还强调了安全考虑,如最高工作压力限制在5bar以下,温度传感器冗余设计等。未来的研究方向包括多尺度建模、新型换热结构和智能控制等方面。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值