// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== namespace System { using System; using System.Globalization; using System.Text; using Microsoft.Win32; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Diagnostics.Contracts; // Represents a Globally Unique Identifier. [StructLayout(LayoutKind.Sequential)] [Serializable] [System.Runtime.InteropServices.ComVisible(true)] [System.Runtime.Versioning.NonVersionable] // This only applies to field layout public partial struct Guid : IFormattable, IComparable #if GENERICS_WORK , IComparable, IEquatable #endif { public static readonly Guid Empty = new Guid(); //////////////////////////////////////////////////////////////////////////////// // Member variables //////////////////////////////////////////////////////////////////////////////// private int _a; private short _b; private short _c; private byte _d; private byte _e; private byte _f; private byte _g; private byte _h; private byte _i; private byte _j; private byte _k; //////////////////////////////////////////////////////////////////////////////// // Constructors //////////////////////////////////////////////////////////////////////////////// // Creates a new guid from an array of bytes. // public Guid(byte[] b) { if (b==null) throw new ArgumentNullException("b"); if (b.Length != 16) throw new ArgumentException(Environment.GetResourceString("Arg_GuidArrayCtor", "16")); Contract.EndContractBlock(); _a = ((int)b[3] << 24) | ((int)b[2] << 16) | ((int)b[1] << 8) | b[0]; _b = (short)(((int)b[5] << 8) | b[4]); _c = (short)(((int)b[7] << 8) | b[6]); _d = b[8]; _e = b[9]; _f = b[10]; _g = b[11]; _h = b[12]; _i = b[13]; _j = b[14]; _k = b[15]; } [CLSCompliant(false)] public Guid (uint a, ushort b, ushort c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k) { _a = (int)a; _b = (short)b; _c = (short)c; _d = d; _e = e; _f = f; _g = g; _h = h; _i = i; _j = j; _k = k; } // Creates a new GUID initialized to the value represented by the arguments. // public Guid(int a, short b, short c, byte[] d) { if (d==null) throw new ArgumentNullException("d"); // Check that array is not too big if(d.Length != 8) throw new ArgumentException(Environment.GetResourceString("Arg_GuidArrayCtor", "8")); Contract.EndContractBlock(); _a = a; _b = b; _c = c; _d = d[0]; _e = d[1]; _f = d[2]; _g = d[3]; _h = d[4]; _i = d[5]; _j = d[6]; _k = d[7]; } // Creates a new GUID initialized to the value represented by the // arguments. The bytes are specified like this to avoid endianness issues. // public Guid(int a, short b, short c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k) { _a = a; _b = b; _c = c; _d = d; _e = e; _f = f; _g = g; _h = h; _i = i; _j = j; _k = k; } [Flags] private enum GuidStyles { None = 0x00000000, AllowParenthesis = 0x00000001, //Allow the guid to be enclosed in parens AllowBraces = 0x00000002, //Allow the guid to be enclosed in braces AllowDashes = 0x00000004, //Allow the guid to contain dash group separators AllowHexPrefix = 0x00000008, //Allow the guid to contain {0xdd,0xdd} RequireParenthesis = 0x00000010, //Require the guid to be enclosed in parens RequireBraces = 0x00000020, //Require the guid to be enclosed in braces RequireDashes = 0x00000040, //Require the guid to contain dash group separators RequireHexPrefix = 0x00000080, //Require the guid to contain {0xdd,0xdd} HexFormat = RequireBraces | RequireHexPrefix, /* X */ NumberFormat = None, /* N */ DigitFormat = RequireDashes, /* D */ BraceFormat = RequireBraces | RequireDashes, /* B */ ParenthesisFormat = RequireParenthesis | RequireDashes, /* P */ Any = AllowParenthesis | AllowBraces | AllowDashes | AllowHexPrefix, } private enum GuidParseThrowStyle { None = 0, All = 1, AllButOverflow = 2 } private enum ParseFailureKind { None = 0, ArgumentNull = 1, Format = 2, FormatWithParameter = 3, NativeException = 4, FormatWithInnerException = 5 } // This will store the result of the parsing. And it will eventually be used to construct a Guid instance. private struct GuidResult { internal Guid parsedGuid; internal GuidParseThrowStyle throwStyle; internal ParseFailureKind m_failure; internal string m_failureMessageID; internal object m_failureMessageFormatArgument; internal string m_failureArgumentName; internal Exception m_innerException; internal void Init(GuidParseThrowStyle canThrow) { parsedGuid = Guid.Empty; throwStyle = canThrow; } internal void SetFailure(Exception nativeException) { m_failure = ParseFailureKind.NativeException; m_innerException = nativeException; } internal void SetFailure(ParseFailureKind failure, string failureMessageID) { SetFailure(failure, failureMessageID, null, null, null); } internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument) { SetFailure(failure, failureMessageID, failureMessageFormatArgument, null, null); } internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument, string failureArgumentName, Exception innerException) { Contract.Assert(failure != ParseFailureKind.NativeException, "ParseFailureKind.NativeException should not be used with this overload"); m_failure = failure; m_failureMessageID = failureMessageID; m_failureMessageFormatArgument = failureMessageFormatArgument; m_failureArgumentName = failureArgumentName; m_innerException = innerException; if (throwStyle != GuidParseThrowStyle.None) { throw GetGuidParseException(); } } internal Exception GetGuidParseException() { switch (m_failure) { case ParseFailureKind.ArgumentNull: return new ArgumentNullException(m_failureArgumentName, Environment.GetResourceString(m_failureMessageID)); case ParseFailureKind.FormatWithInnerException: return new FormatException(Environment.GetResourceString(m_failureMessageID), m_innerException); case ParseFailureKind.FormatWithParameter: return new FormatException(Environment.GetResourceString(m_failureMessageID, m_failureMessageFormatArgument)); case ParseFailureKind.Format: return new FormatException(Environment.GetResourceString(m_failureMessageID)); case ParseFailureKind.NativeException: return m_innerException; default: Contract.Assert(false, "Unknown GuidParseFailure: " + m_failure); return new FormatException(Environment.GetResourceString("Format_GuidUnrecognized")); } } } // Creates a new guid based on the value in the string. The value is made up // of hex digits speared by the dash ("-"). The string may begin and end with // brackets ("{", "}"). // // The string must be of the form dddddddd-dddd-dddd-dddd-dddddddddddd. where // d is a hex digit. (That is 8 hex digits, followed by 4, then 4, then 4, // then 12) such as: "CA761232-ED42-11CE-BACD-00AA0057B223" // public Guid(String g) { if (g==null) { throw new ArgumentNullException("g"); } Contract.EndContractBlock(); this = Guid.Empty; GuidResult result = new GuidResult(); result.Init(GuidParseThrowStyle.All); if (TryParseGuid(g, GuidStyles.Any, ref result)) { this = result.parsedGuid; } else { throw result.GetGuidParseException(); } } public static Guid Parse(String input) { if (input == null) { throw new ArgumentNullException("input"); } Contract.EndContractBlock(); GuidResult result = new GuidResult(); result.Init(GuidParseThrowStyle.AllButOverflow); if (TryParseGuid(input, GuidStyles.Any, ref result)) { return result.parsedGuid; } else { throw result.GetGuidParseException(); } } public static bool TryParse(String input, out Guid result) { GuidResult parseResult = new GuidResult(); parseResult.Init(GuidParseThrowStyle.None); if (TryParseGuid(input, GuidStyles.Any, ref parseResult)) { result = parseResult.parsedGuid; return true; } else { result = Guid.Empty; return false; } } public static Guid ParseExact(String input, String format) { if (input == null) throw new ArgumentNullException("input"); if (format == null) throw new ArgumentNullException("format"); if( format.Length != 1) { // all acceptable format strings are of length 1 throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification")); } GuidStyles style; char formatCh = format[0]; if (formatCh == 'D' || formatCh == 'd') { style = GuidStyles.DigitFormat; } else if (formatCh == 'N' || formatCh == 'n') { style = GuidStyles.NumberFormat; } else if (formatCh == 'B' || formatCh == 'b') { style = GuidStyles.BraceFormat; } else if (formatCh == 'P' || formatCh == 'p') { style = GuidStyles.ParenthesisFormat; } else if (formatCh == 'X' || formatCh == 'x') { style = GuidStyles.HexFormat; } else { throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification")); } GuidResult result = new GuidResult(); result.Init(GuidParseThrowStyle.AllButOverflow); if (TryParseGuid(input, style, ref result)) { return result.parsedGuid; } else { throw result.GetGuidParseException(); } } public static bool TryParseExact(String input, String format, out Guid result) { if (format == null || format.Length != 1) { result = Guid.Empty; return false; } GuidStyles style; char formatCh = format[0]; if (formatCh == 'D' || formatCh == 'd') { style = GuidStyles.DigitFormat; } else if (formatCh == 'N' || formatCh == 'n') { style = GuidStyles.NumberFormat; } else if (formatCh == 'B' || formatCh == 'b') { style = GuidStyles.BraceFormat; } else if (formatCh == 'P' || formatCh == 'p') { style = GuidStyles.ParenthesisFormat; } else if (formatCh == 'X' || formatCh == 'x') { style = GuidStyles.HexFormat; } else { // invalid guid format specification result = Guid.Empty; return false; } GuidResult parseResult = new GuidResult(); parseResult.Init(GuidParseThrowStyle.None); if (TryParseGuid(input, style, ref parseResult)) { result = parseResult.parsedGuid; return true; } else { result = Guid.Empty; return false; } } private static bool TryParseGuid(String g, GuidStyles flags, ref GuidResult result) { if (g == null) { result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); return false; } String guidString = g.Trim(); //Remove Whitespace if (guidString.Length == 0) { result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); return false; } // Check for dashes bool dashesExistInString = (guidString.IndexOf('-', 0) >= 0); if (dashesExistInString) { if ((flags & (GuidStyles.AllowDashes | GuidStyles.RequireDashes)) == 0) { // dashes are not allowed result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); return false; } } else { if ((flags & GuidStyles.RequireDashes) != 0) { // dashes are required result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); return false; } } // Check for braces bool bracesExistInString = (guidString.IndexOf('{', 0) >= 0); if (bracesExistInString) { if ((flags & (GuidStyles.AllowBraces | GuidStyles.RequireBraces)) == 0) { // braces are not allowed result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); return false; } } else { if ((flags & GuidStyles.RequireBraces) != 0) { // braces are required result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); return false; } } // Check for parenthesis bool parenthesisExistInString = (guidString.IndexOf('(', 0) >= 0); if (parenthesisExistInString) { if ((flags & (GuidStyles.AllowParenthesis | GuidStyles.RequireParenthesis)) == 0) { // parenthesis are not allowed result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); return false; } } else { if ((flags & GuidStyles.RequireParenthesis) != 0) { // parenthesis are required result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); return false; } } try { // let's get on with the parsing if (dashesExistInString) { // Check if it's of the form [{|(]dddddddd-dddd-dddd-dddd-dddddddddddd[}|)] return TryParseGuidWithDashes(guidString, ref result); } else if (bracesExistInString) { // Check if it's of the form {0xdddddddd,0xdddd,0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}} return TryParseGuidWithHexPrefix(guidString, ref result); } else { // Check if it's of the form dddddddddddddddddddddddddddddddd return TryParseGuidWithNoStyle(guidString, ref result); } } catch(IndexOutOfRangeException ex) { result.SetFailure(ParseFailureKind.FormatWithInnerException, "Format_GuidUnrecognized", null, null, ex); return false; } catch (ArgumentException ex) { result.SetFailure(ParseFailureKind.FormatWithInnerException, "Format_GuidUnrecognized", null, null, ex); return false; } } // Check if it's of the form {0xdddddddd,0xdddd,0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}} private static bool TryParseGuidWithHexPrefix(String guidString, ref GuidResult result) { int numStart = 0; int numLen = 0; // Eat all of the whitespace guidString = EatAllWhitespace(guidString); // Check for leading '{' if(String.IsNullOrEmpty(guidString) || guidString[0] != '{') { result.SetFailure(ParseFailureKind.Format, "Format_GuidBrace"); return false; } // Check for '0x' if(!IsHexPrefix(guidString, 1)) { result.SetFailure(ParseFailureKind.Format, "Format_GuidHexPrefix", "{0xdddddddd, etc}"); return false; } // Find the end of this hex number (since it is not fixed length) numStart = 3; numLen = guidString.IndexOf(',', numStart) - numStart; if(numLen <= 0) { result.SetFailure(ParseFailureKind.Format, "Format_GuidComma"); return false; } if (!StringToInt(guidString.Substring(numStart, numLen) /*first DWORD*/, -1, ParseNumbers.IsTight, out result.parsedGuid._a, ref result)) return false; // Check for '0x' if(!IsHexPrefix(guidString, numStart+numLen+1)) { result.SetFailure(ParseFailureKind.Format, "Format_GuidHexPrefix", "{0xdddddddd, 0xdddd, etc}"); return false; } // +3 to get by ',0x' numStart = numStart + numLen + 3; numLen = guidString.IndexOf(',', numStart) - numStart; if(numLen <= 0) { result.SetFailure(ParseFailureKind.Format, "Format_GuidComma"); return false; } // Read in the number if (!StringToShort(guidString.Substring(numStart, numLen) /*first DWORD*/, -1, ParseNumbers.IsTight, out result.parsedGuid._b, ref result)) return false; // Check for '0x' if(!IsHexPrefix(guidString, numStart+numLen+1)) { result.SetFailure(ParseFailureKind.Format, "Format_GuidHexPrefix", "{0xdddddddd, 0xdddd, 0xdddd, etc}"); return false; } // +3 to get by ',0x' numStart = numStart + numLen + 3; numLen = guidString.IndexOf(',', numStart) - numStart; if(numLen <= 0) { result.SetFailure(ParseFailureKind.Format, "Format_GuidComma"); return false; } // Read in the number if (!StringToShort(guidString.Substring(numStart, numLen) /*first DWORD*/, -1, ParseNumbers.IsTight, out result.parsedGuid._c, ref result)) return false; // Check for '{' if(guidString.Length <= numStart+numLen+1 || guidString[numStart+numLen+1] != '{') { result.SetFailure(ParseFailureKind.Format, "Format_GuidBrace"); return false; } // Prepare for loop numLen++; byte[] bytes = new byte[8]; for(int i = 0; i < 8; i++) { // Check for '0x' if(!IsHexPrefix(guidString, numStart+numLen+1)) { result.SetFailure(ParseFailureKind.Format, "Format_GuidHexPrefix", "{... { ... 0xdd, ...}}"); return false; } // +3 to get by ',0x' or '{0x' for first case numStart = numStart + numLen + 3; // Calculate number length if(i < 7) // first 7 cases { numLen = guidString.IndexOf(',', numStart) - numStart; if(numLen <= 0) { result.SetFailure(ParseFailureKind.Format, "Format_GuidComma"); return false; } } else // last case ends with '}', not ',' { numLen = guidString.IndexOf('}', numStart) - numStart; if(numLen <= 0) { result.SetFailure(ParseFailureKind.Format, "Format_GuidBraceAfterLastNumber"); return false; } } // Read in the number uint number = (uint)Convert.ToInt32(guidString.Substring(numStart, numLen),16); // check for overflow if(number > 255) { result.SetFailure(ParseFailureKind.Format, "Overflow_Byte"); return false; } bytes[i] = (byte)number; } result.parsedGuid._d = bytes[0]; result.parsedGuid._e = bytes[1]; result.parsedGuid._f = bytes[2]; result.parsedGuid._g = bytes[3]; result.parsedGuid._h = bytes[4]; result.parsedGuid._i = bytes[5]; result.parsedGuid._j = bytes[6]; result.parsedGuid._k = bytes[7]; // Check for last '}' if(numStart+numLen+1 >= guidString.Length || guidString[numStart+numLen+1] != '}') { result.SetFailure(ParseFailureKind.Format, "Format_GuidEndBrace"); return false; } // Check if we have extra characters at the end if( numStart+numLen+1 != guidString.Length -1) { result.SetFailure(ParseFailureKind.Format, "Format_ExtraJunkAtEnd"); return false; } return true; } // Check if it's of the form dddddddddddddddddddddddddddddddd private static bool TryParseGuidWithNoStyle(String guidString, ref GuidResult result) { int startPos=0; int temp; long templ; int currentPos = 0; if(guidString.Length != 32) { result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); return false; } for(int i= 0; i< guidString.Length; i++) { char ch = guidString[i]; if(ch >= '0' && ch <= '9') { continue; } else { char upperCaseCh = Char.ToUpper(ch, CultureInfo.InvariantCulture); if(upperCaseCh >= 'A' && upperCaseCh <= 'F') { continue; } } result.SetFailure(ParseFailureKind.Format, "Format_GuidInvalidChar"); return false; } if (!StringToInt(guidString.Substring(startPos, 8) /*first DWORD*/, -1, ParseNumbers.IsTight, out result.parsedGuid._a, ref result)) return false; startPos += 8; if (!StringToShort(guidString.Substring(startPos, 4), -1, ParseNumbers.IsTight, out result.parsedGuid._b, ref result)) return false; startPos += 4; if (!StringToShort(guidString.Substring(startPos, 4), -1, ParseNumbers.IsTight, out result.parsedGuid._c, ref result)) return false; startPos += 4; if (!StringToInt(guidString.Substring(startPos, 4), -1, ParseNumbers.IsTight, out temp, ref result)) return false; startPos += 4; currentPos = startPos; if (!StringToLong(guidString, ref currentPos, ParseNumbers.NoSpace, out templ, ref result)) return false; if (currentPos - startPos!=12) { result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); return false; } result.parsedGuid._d = (byte)(temp>>8); result.parsedGuid._e = (byte)(temp); temp = (int)(templ >> 32); result.parsedGuid._f = (byte)(temp>>8); result.parsedGuid._g = (byte)(temp); temp = (int)(templ); result.parsedGuid._h = (byte)(temp>>24); result.parsedGuid._i = (byte)(temp>>16); result.parsedGuid._j = (byte)(temp>>8); result.parsedGuid._k = (byte)(temp); return true; } // Check if it's of the form [{|(]dddddddd-dddd-dddd-dddd-dddddddddddd[}|)] private static bool TryParseGuidWithDashes(String guidString, ref GuidResult result) { int startPos=0; int temp; long templ; int currentPos = 0; // check to see that it's the proper length if (guidString[0]=='{') { if (guidString.Length!=38 || guidString[37]!='}') { result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); return false; } startPos=1; } else if (guidString[0]=='(') { if (guidString.Length!=38 || guidString[37]!=')') { result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); return false; } startPos=1; } else if(guidString.Length != 36) { result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); return false; } if (guidString[8+startPos] != '-' || guidString[13+startPos] != '-' || guidString[18+startPos] != '-' || guidString[23+startPos] != '-') { result.SetFailure(ParseFailureKind.Format, "Format_GuidDashes"); return false; } currentPos = startPos; if (!StringToInt(guidString, ref currentPos, 8, ParseNumbers.NoSpace, out temp, ref result)) return false; result.parsedGuid._a = temp; ++currentPos; //Increment past the '-'; if (!StringToInt(guidString, ref currentPos, 4, ParseNumbers.NoSpace, out temp, ref result)) return false; result.parsedGuid._b = (short)temp; ++currentPos; //Increment past the '-'; if (!StringToInt(guidString, ref currentPos, 4, ParseNumbers.NoSpace, out temp, ref result)) return false; result.parsedGuid._c = (short)temp; ++currentPos; //Increment past the '-'; if (!StringToInt(guidString, ref currentPos, 4, ParseNumbers.NoSpace, out temp, ref result)) return false; ++currentPos; //Increment past the '-'; startPos=currentPos; if (!StringToLong(guidString, ref currentPos, ParseNumbers.NoSpace, out templ, ref result)) return false; if (currentPos - startPos != 12) { result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); return false; } result.parsedGuid._d = (byte)(temp>>8); result.parsedGuid._e = (byte)(temp); temp = (int)(templ >> 32); result.parsedGuid._f = (byte)(temp>>8); result.parsedGuid._g = (byte)(temp); temp = (int)(templ); result.parsedGuid._h = (byte)(temp>>24); result.parsedGuid._i = (byte)(temp>>16); result.parsedGuid._j = (byte)(temp>>8); result.parsedGuid._k = (byte)(temp); return true; } // // StringToShort, StringToInt, and StringToLong are wrappers around COMUtilNative integer parsing routines; //< [System.Security.SecuritySafeCritical] private static unsafe bool StringToShort(String str, int requiredLength, int flags, out short result, ref GuidResult parseResult) { return StringToShort(str, null, requiredLength, flags, out result, ref parseResult); } [System.Security.SecuritySafeCritical] private static unsafe bool StringToShort(String str, ref int parsePos, int requiredLength, int flags, out short result, ref GuidResult parseResult) { fixed(int * ppos = &parsePos) { return StringToShort(str, ppos, requiredLength, flags, out result, ref parseResult); } } [System.Security.SecurityCritical] private static unsafe bool StringToShort(String str, int* parsePos, int requiredLength, int flags, out short result, ref GuidResult parseResult) { result = 0; int x; bool retValue = StringToInt(str, parsePos, requiredLength, flags, out x, ref parseResult); result = (short)x; return retValue; } [System.Security.SecuritySafeCritical] private static unsafe bool StringToInt(String str, int requiredLength, int flags, out int result, ref GuidResult parseResult) { return StringToInt(str, null, requiredLength, flags, out result, ref parseResult); } [System.Security.SecuritySafeCritical] private static unsafe bool StringToInt(String str, ref int parsePos, int requiredLength, int flags, out int result, ref GuidResult parseResult) { fixed(int * ppos = &parsePos) { return StringToInt(str, ppos, requiredLength, flags, out result, ref parseResult); } } [System.Security.SecurityCritical] private static unsafe bool StringToInt(String str, int* parsePos, int requiredLength, int flags, out int result, ref GuidResult parseResult) { result = 0; int currStart = (parsePos == null) ? 0 : (*parsePos); try { result = ParseNumbers.StringToInt(str, 16, flags, parsePos); } catch (OverflowException ex) { if (parseResult.throwStyle == GuidParseThrowStyle.All) { throw; } else if (parseResult.throwStyle == GuidParseThrowStyle.AllButOverflow) { throw new FormatException(Environment.GetResourceString("Format_GuidUnrecognized"), ex); } else { parseResult.SetFailure(ex); return false; } } catch (Exception ex) { if (parseResult.throwStyle == GuidParseThrowStyle.None) { parseResult.SetFailure(ex); return false; } else { throw; } } //If we didn't parse enough characters, there's clearly an error. if (requiredLength != -1 && parsePos != null && (*parsePos) - currStart != requiredLength) { parseResult.SetFailure(ParseFailureKind.Format, "Format_GuidInvalidChar"); return false; } return true; } [System.Security.SecuritySafeCritical] private static unsafe bool StringToLong(String str, int flags, out long result, ref GuidResult parseResult) { return StringToLong(str, null, flags, out result, ref parseResult); } [System.Security.SecuritySafeCritical] private static unsafe bool StringToLong(String str, ref int parsePos, int flags, out long result, ref GuidResult parseResult) { fixed(int * ppos = &parsePos) { return StringToLong(str, ppos, flags, out result, ref parseResult); } } [System.Security.SecuritySafeCritical] private static unsafe bool StringToLong(String str, int* parsePos, int flags, out long result, ref GuidResult parseResult) { result = 0; try { result = ParseNumbers.StringToLong(str, 16, flags, parsePos); } catch (OverflowException ex) { if (parseResult.throwStyle == GuidParseThrowStyle.All) { throw; } else if (parseResult.throwStyle == GuidParseThrowStyle.AllButOverflow) { throw new FormatException(Environment.GetResourceString("Format_GuidUnrecognized"), ex); } else { parseResult.SetFailure(ex); return false; } } catch (Exception ex) { if (parseResult.throwStyle == GuidParseThrowStyle.None) { parseResult.SetFailure(ex); return false; } else { throw; } } return true; } private static String EatAllWhitespace(String str) { int newLength = 0; char[] chArr = new char[str.Length]; char curChar; // Now get each char from str and if it is not whitespace add it to chArr for(int i = 0; i < str.Length; i++) { curChar = str[i]; if(!Char.IsWhiteSpace(curChar)) { chArr[newLength++] = curChar; } } // Return a new string based on chArr return new String(chArr, 0, newLength); } private static bool IsHexPrefix(String str, int i) { if(str.Length > i+1 && str[i] == '0' && (Char.ToLower(str[i+1], CultureInfo.InvariantCulture) == 'x')) return true; else return false; } // Returns an unsigned byte array containing the GUID. public byte[] ToByteArray() { byte[] g = new byte[16]; g[0] = (byte)(_a); g[1] = (byte)(_a >> 8); g[2] = (byte)(_a >> 16); g[3] = (byte)(_a >> 24); g[4] = (byte)(_b); g[5] = (byte)(_b >> 8); g[6] = (byte)(_c); g[7] = (byte)(_c >> 8); g[8] = _d; g[9] = _e; g[10] = _f; g[11] = _g; g[12] = _h; g[13] = _i; g[14] = _j; g[15] = _k; return g; } // Returns the guid in "registry" format. public override String ToString() { return ToString("D",null); } public override int GetHashCode() { return _a ^ (((int)_b << 16) | (int)(ushort)_c) ^ (((int)_f << 24) | _k); } // Returns true if and only if the guid represented // by o is the same as this instance. public override bool Equals(Object o) { Guid g; // Check that o is a Guid first if(o == null || !(o is Guid)) return false; else g = (Guid) o; // Now compare each of the elements if(g._a != _a) return false; if(g._b != _b) return false; if(g._c != _c) return false; if (g._d != _d) return false; if (g._e != _e) return false; if (g._f != _f) return false; if (g._g != _g) return false; if (g._h != _h) return false; if (g._i != _i) return false; if (g._j != _j) return false; if (g._k != _k) return false; return true; } public bool Equals(Guid g) { // Now compare each of the elements if(g._a != _a) return false; if(g._b != _b) return false; if(g._c != _c) return false; if (g._d != _d) return false; if (g._e != _e) return false; if (g._f != _f) return false; if (g._g != _g) return false; if (g._h != _h) return false; if (g._i != _i) return false; if (g._j != _j) return false; if (g._k != _k) return false; return true; } private int GetResult(uint me, uint them) { if (me() != Guid.Empty); Guid guid; Marshal.ThrowExceptionForHR(Win32Native.CoCreateGuid(out guid), new IntPtr(-1)); return guid; } #endif public String ToString(String format) { return ToString(format, null); } private static char HexToChar(int a) { a = a & 0xf; return (char) ((a > 9) ? a - 10 + 0x61 : a + 0x30); } [System.Security.SecurityCritical] unsafe private static int HexsToChars(char* guidChars, int offset, int a, int b) { return HexsToChars(guidChars, offset, a, b, false); } [System.Security.SecurityCritical] unsafe private static int HexsToChars(char* guidChars, int offset, int a, int b, bool hex) { if (hex) { guidChars[offset++] = '0'; guidChars[offset++] = 'x'; } guidChars[offset++] = HexToChar(a>>4); guidChars[offset++] = HexToChar(a); if (hex) { guidChars[offset++] = ','; guidChars[offset++] = '0'; guidChars[offset++] = 'x'; } guidChars[offset++] = HexToChar(b>>4); guidChars[offset++] = HexToChar(b); return offset; } // IFormattable interface // We currently ignore provider [System.Security.SecuritySafeCritical] public String ToString(String format, IFormatProvider provider) { if (format == null || format.Length == 0) format = "D"; string guidString; int offset = 0; bool dash = true; bool hex = false; if( format.Length != 1) { // all acceptable format strings are of length 1 throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification")); } char formatCh = format[0]; if (formatCh == 'D' || formatCh == 'd') { guidString = string.FastAllocateString(36); } else if (formatCh == 'N' || formatCh == 'n') { guidString = string.FastAllocateString(32); dash = false; } else if (formatCh == 'B' || formatCh == 'b') { guidString = string.FastAllocateString(38); unsafe { fixed (char* guidChars = guidString) { guidChars[offset++] = '{'; guidChars[37] = '}'; } } } else if (formatCh == 'P' || formatCh == 'p') { guidString = string.FastAllocateString(38); unsafe { fixed (char* guidChars = guidString) { guidChars[offset++] = '('; guidChars[37] = ')'; } } } else if (formatCh == 'X' || formatCh == 'x') { guidString = string.FastAllocateString(68); unsafe { fixed (char* guidChars = guidString) { guidChars[offset++] = '{'; guidChars[67] = '}'; } } dash = false; hex = true; } else { throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification")); } unsafe { fixed (char* guidChars = guidString) { if (hex) { // {0xdddddddd,0xdddd,0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}} guidChars[offset++] = '0'; guidChars[offset++] = 'x'; offset = HexsToChars(guidChars, offset, _a >> 24, _a >> 16); offset = HexsToChars(guidChars, offset, _a >> 8, _a); guidChars[offset++] = ','; guidChars[offset++] = '0'; guidChars[offset++] = 'x'; offset = HexsToChars(guidChars, offset, _b >> 8, _b); guidChars[offset++] = ','; guidChars[offset++] = '0'; guidChars[offset++] = 'x'; offset = HexsToChars(guidChars, offset, _c >> 8, _c); guidChars[offset++] = ','; guidChars[offset++] = '{'; offset = HexsToChars(guidChars, offset, _d, _e, true); guidChars[offset++] = ','; offset = HexsToChars(guidChars, offset, _f, _g, true); guidChars[offset++] = ','; offset = HexsToChars(guidChars, offset, _h, _i, true); guidChars[offset++] = ','; offset = HexsToChars(guidChars, offset, _j, _k, true); guidChars[offset++] = '}'; } else { // [{|(]dddddddd[-]dddd[-]dddd[-]dddd[-]dddddddddddd[}|)] offset = HexsToChars(guidChars, offset, _a >> 24, _a >> 16); offset = HexsToChars(guidChars, offset, _a >> 8, _a); if (dash) guidChars[offset++] = '-'; offset = HexsToChars(guidChars, offset, _b >> 8, _b); if (dash) guidChars[offset++] = '-'; offset = HexsToChars(guidChars, offset, _c >> 8, _c); if (dash) guidChars[offset++] = '-'; offset = HexsToChars(guidChars, offset, _d, _e); if (dash) guidChars[offset++] = '-'; offset = HexsToChars(guidChars, offset, _f, _g); offset = HexsToChars(guidChars, offset, _h, _i); offset = HexsToChars(guidChars, offset, _j, _k); } } } return guidString; } } }