1 // ==++== 2 // 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // 5 // ==--== 6 namespace System { 7 8 using System; 9 using System.Globalization; 10 using System.Text; 11 using Microsoft.Win32; 12 using System.Runtime.InteropServices; 13 using System.Runtime.CompilerServices; 14 using System.Diagnostics.Contracts; 15 16 // Represents a Globally Unique Identifier. 17 [StructLayout(LayoutKind.Sequential)] 18 [Serializable] 19 [System.Runtime.InteropServices.ComVisible(true)] 20 [System.Runtime.Versioning.NonVersionable] // This only applies to field layout 21 public partial struct Guid : IFormattable, IComparable 22 #if GENERICS_WORK 23 , IComparable<Guid>, IEquatable<Guid> 24 #endif 25 { 26 public static readonly Guid Empty = new Guid(); 27 //////////////////////////////////////////////////////////////////////////////// 28 // Member variables 29 //////////////////////////////////////////////////////////////////////////////// 30 private int _a; 31 private short _b; 32 private short _c; 33 private byte _d; 34 private byte _e; 35 private byte _f; 36 private byte _g; 37 private byte _h; 38 private byte _i; 39 private byte _j; 40 private byte _k; 41 42 43 44 //////////////////////////////////////////////////////////////////////////////// 45 // Constructors 46 //////////////////////////////////////////////////////////////////////////////// 47 48 // Creates a new guid from an array of bytes. 49 // GuidSystem.Guid50 public Guid(byte[] b) 51 { 52 if (b==null) 53 throw new ArgumentNullException("b"); 54 if (b.Length != 16) 55 throw new ArgumentException(Environment.GetResourceString("Arg_GuidArrayCtor", "16")); 56 Contract.EndContractBlock(); 57 58 _a = ((int)b[3] << 24) | ((int)b[2] << 16) | ((int)b[1] << 8) | b[0]; 59 _b = (short)(((int)b[5] << 8) | b[4]); 60 _c = (short)(((int)b[7] << 8) | b[6]); 61 _d = b[8]; 62 _e = b[9]; 63 _f = b[10]; 64 _g = b[11]; 65 _h = b[12]; 66 _i = b[13]; 67 _j = b[14]; 68 _k = b[15]; 69 } 70 71 [CLSCompliant(false)] GuidSystem.Guid72 public Guid (uint a, ushort b, ushort c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k) 73 { 74 _a = (int)a; 75 _b = (short)b; 76 _c = (short)c; 77 _d = d; 78 _e = e; 79 _f = f; 80 _g = g; 81 _h = h; 82 _i = i; 83 _j = j; 84 _k = k; 85 } 86 87 88 // Creates a new GUID initialized to the value represented by the arguments. 89 // GuidSystem.Guid90 public Guid(int a, short b, short c, byte[] d) 91 { 92 if (d==null) 93 throw new ArgumentNullException("d"); 94 // Check that array is not too big 95 if(d.Length != 8) 96 throw new ArgumentException(Environment.GetResourceString("Arg_GuidArrayCtor", "8")); 97 Contract.EndContractBlock(); 98 99 _a = a; 100 _b = b; 101 _c = c; 102 _d = d[0]; 103 _e = d[1]; 104 _f = d[2]; 105 _g = d[3]; 106 _h = d[4]; 107 _i = d[5]; 108 _j = d[6]; 109 _k = d[7]; 110 } 111 112 // Creates a new GUID initialized to the value represented by the 113 // arguments. The bytes are specified like this to avoid endianness issues. 114 // GuidSystem.Guid115 public Guid(int a, short b, short c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k) 116 { 117 _a = a; 118 _b = b; 119 _c = c; 120 _d = d; 121 _e = e; 122 _f = f; 123 _g = g; 124 _h = h; 125 _i = i; 126 _j = j; 127 _k = k; 128 } 129 130 [Flags] 131 private enum GuidStyles { 132 None = 0x00000000, 133 AllowParenthesis = 0x00000001, //Allow the guid to be enclosed in parens 134 AllowBraces = 0x00000002, //Allow the guid to be enclosed in braces 135 AllowDashes = 0x00000004, //Allow the guid to contain dash group separators 136 AllowHexPrefix = 0x00000008, //Allow the guid to contain {0xdd,0xdd} 137 RequireParenthesis = 0x00000010, //Require the guid to be enclosed in parens 138 RequireBraces = 0x00000020, //Require the guid to be enclosed in braces 139 RequireDashes = 0x00000040, //Require the guid to contain dash group separators 140 RequireHexPrefix = 0x00000080, //Require the guid to contain {0xdd,0xdd} 141 142 HexFormat = RequireBraces | RequireHexPrefix, /* X */ 143 NumberFormat = None, /* N */ 144 DigitFormat = RequireDashes, /* D */ 145 BraceFormat = RequireBraces | RequireDashes, /* B */ 146 ParenthesisFormat = RequireParenthesis | RequireDashes, /* P */ 147 148 Any = AllowParenthesis | AllowBraces | AllowDashes | AllowHexPrefix, 149 } 150 private enum GuidParseThrowStyle { 151 None = 0, 152 All = 1, 153 AllButOverflow = 2 154 } 155 private enum ParseFailureKind { 156 None = 0, 157 ArgumentNull = 1, 158 Format = 2, 159 FormatWithParameter = 3, 160 NativeException = 4, 161 FormatWithInnerException = 5 162 } 163 164 // This will store the result of the parsing. And it will eventually be used to construct a Guid instance. 165 private struct GuidResult { 166 internal Guid parsedGuid; 167 internal GuidParseThrowStyle throwStyle; 168 169 internal ParseFailureKind m_failure; 170 internal string m_failureMessageID; 171 internal object m_failureMessageFormatArgument; 172 internal string m_failureArgumentName; 173 internal Exception m_innerException; 174 InitSystem.Guid.GuidResult175 internal void Init(GuidParseThrowStyle canThrow) { 176 parsedGuid = Guid.Empty; 177 throwStyle = canThrow; 178 } SetFailureSystem.Guid.GuidResult179 internal void SetFailure(Exception nativeException) { 180 m_failure = ParseFailureKind.NativeException; 181 m_innerException = nativeException; 182 } SetFailureSystem.Guid.GuidResult183 internal void SetFailure(ParseFailureKind failure, string failureMessageID) { 184 SetFailure(failure, failureMessageID, null, null, null); 185 } SetFailureSystem.Guid.GuidResult186 internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument) { 187 SetFailure(failure, failureMessageID, failureMessageFormatArgument, null, null); 188 } SetFailureSystem.Guid.GuidResult189 internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument, 190 string failureArgumentName, Exception innerException) { 191 Contract.Assert(failure != ParseFailureKind.NativeException, "ParseFailureKind.NativeException should not be used with this overload"); 192 m_failure = failure; 193 m_failureMessageID = failureMessageID; 194 m_failureMessageFormatArgument = failureMessageFormatArgument; 195 m_failureArgumentName = failureArgumentName; 196 m_innerException = innerException; 197 if (throwStyle != GuidParseThrowStyle.None) { 198 throw GetGuidParseException(); 199 } 200 } 201 GetGuidParseExceptionSystem.Guid.GuidResult202 internal Exception GetGuidParseException() { 203 switch (m_failure) { 204 case ParseFailureKind.ArgumentNull: 205 return new ArgumentNullException(m_failureArgumentName, Environment.GetResourceString(m_failureMessageID)); 206 207 case ParseFailureKind.FormatWithInnerException: 208 return new FormatException(Environment.GetResourceString(m_failureMessageID), m_innerException); 209 210 case ParseFailureKind.FormatWithParameter: 211 return new FormatException(Environment.GetResourceString(m_failureMessageID, m_failureMessageFormatArgument)); 212 213 case ParseFailureKind.Format: 214 return new FormatException(Environment.GetResourceString(m_failureMessageID)); 215 216 case ParseFailureKind.NativeException: 217 return m_innerException; 218 219 default: 220 Contract.Assert(false, "Unknown GuidParseFailure: " + m_failure); 221 return new FormatException(Environment.GetResourceString("Format_GuidUnrecognized")); 222 } 223 } 224 } 225 226 // Creates a new guid based on the value in the string. The value is made up 227 // of hex digits speared by the dash ("-"). The string may begin and end with 228 // brackets ("{", "}"). 229 // 230 // The string must be of the form dddddddd-dddd-dddd-dddd-dddddddddddd. where 231 // d is a hex digit. (That is 8 hex digits, followed by 4, then 4, then 4, 232 // then 12) such as: "CA761232-ED42-11CE-BACD-00AA0057B223" 233 // GuidSystem.Guid234 public Guid(String g) 235 { 236 if (g==null) { 237 throw new ArgumentNullException("g"); 238 } 239 Contract.EndContractBlock(); 240 this = Guid.Empty; 241 242 GuidResult result = new GuidResult(); 243 result.Init(GuidParseThrowStyle.All); 244 if (TryParseGuid(g, GuidStyles.Any, ref result)) { 245 this = result.parsedGuid; 246 } 247 else { 248 throw result.GetGuidParseException(); 249 } 250 } 251 252 ParseSystem.Guid253 public static Guid Parse(String input) 254 { 255 if (input == null) { 256 throw new ArgumentNullException("input"); 257 } 258 Contract.EndContractBlock(); 259 260 GuidResult result = new GuidResult(); 261 result.Init(GuidParseThrowStyle.AllButOverflow); 262 if (TryParseGuid(input, GuidStyles.Any, ref result)) { 263 return result.parsedGuid; 264 } 265 else { 266 throw result.GetGuidParseException(); 267 } 268 } 269 TryParseSystem.Guid270 public static bool TryParse(String input, out Guid result) 271 { 272 GuidResult parseResult = new GuidResult(); 273 parseResult.Init(GuidParseThrowStyle.None); 274 if (TryParseGuid(input, GuidStyles.Any, ref parseResult)) { 275 result = parseResult.parsedGuid; 276 return true; 277 } 278 else { 279 result = Guid.Empty; 280 return false; 281 } 282 } 283 ParseExactSystem.Guid284 public static Guid ParseExact(String input, String format) 285 { 286 if (input == null) 287 throw new ArgumentNullException("input"); 288 289 if (format == null) 290 throw new ArgumentNullException("format"); 291 292 if( format.Length != 1) { 293 // all acceptable format strings are of length 1 294 throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification")); 295 } 296 297 GuidStyles style; 298 char formatCh = format[0]; 299 if (formatCh == 'D' || formatCh == 'd') { 300 style = GuidStyles.DigitFormat; 301 } 302 else if (formatCh == 'N' || formatCh == 'n') { 303 style = GuidStyles.NumberFormat; 304 } 305 else if (formatCh == 'B' || formatCh == 'b') { 306 style = GuidStyles.BraceFormat; 307 } 308 else if (formatCh == 'P' || formatCh == 'p') { 309 style = GuidStyles.ParenthesisFormat; 310 } 311 else if (formatCh == 'X' || formatCh == 'x') { 312 style = GuidStyles.HexFormat; 313 } 314 else { 315 throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification")); 316 } 317 318 GuidResult result = new GuidResult(); 319 result.Init(GuidParseThrowStyle.AllButOverflow); 320 if (TryParseGuid(input, style, ref result)) { 321 return result.parsedGuid; 322 } 323 else { 324 throw result.GetGuidParseException(); 325 } 326 } 327 TryParseExactSystem.Guid328 public static bool TryParseExact(String input, String format, out Guid result) 329 { 330 if (format == null || format.Length != 1) { 331 result = Guid.Empty; 332 return false; 333 } 334 335 GuidStyles style; 336 char formatCh = format[0]; 337 338 if (formatCh == 'D' || formatCh == 'd') { 339 style = GuidStyles.DigitFormat; 340 } 341 else if (formatCh == 'N' || formatCh == 'n') { 342 style = GuidStyles.NumberFormat; 343 } 344 else if (formatCh == 'B' || formatCh == 'b') { 345 style = GuidStyles.BraceFormat; 346 } 347 else if (formatCh == 'P' || formatCh == 'p') { 348 style = GuidStyles.ParenthesisFormat; 349 } 350 else if (formatCh == 'X' || formatCh == 'x') { 351 style = GuidStyles.HexFormat; 352 } 353 else { 354 // invalid guid format specification 355 result = Guid.Empty; 356 return false; 357 } 358 359 GuidResult parseResult = new GuidResult(); 360 parseResult.Init(GuidParseThrowStyle.None); 361 if (TryParseGuid(input, style, ref parseResult)) { 362 result = parseResult.parsedGuid; 363 return true; 364 } 365 else { 366 result = Guid.Empty; 367 return false; 368 } 369 } 370 371 TryParseGuidSystem.Guid372 private static bool TryParseGuid(String g, GuidStyles flags, ref GuidResult result) 373 { 374 if (g == null) { 375 result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); 376 return false; 377 } 378 String guidString = g.Trim(); //Remove Whitespace 379 380 if (guidString.Length == 0) { 381 result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); 382 return false; 383 } 384 385 // Check for dashes 386 bool dashesExistInString = (guidString.IndexOf('-', 0) >= 0); 387 388 if (dashesExistInString) { 389 if ((flags & (GuidStyles.AllowDashes | GuidStyles.RequireDashes)) == 0) { 390 // dashes are not allowed 391 result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); 392 return false; 393 } 394 } 395 else { 396 if ((flags & GuidStyles.RequireDashes) != 0) { 397 // dashes are required 398 result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); 399 return false; 400 } 401 } 402 403 // Check for braces 404 bool bracesExistInString = (guidString.IndexOf('{', 0) >= 0); 405 406 if (bracesExistInString) { 407 if ((flags & (GuidStyles.AllowBraces | GuidStyles.RequireBraces)) == 0) { 408 // braces are not allowed 409 result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); 410 return false; 411 } 412 } 413 else { 414 if ((flags & GuidStyles.RequireBraces) != 0) { 415 // braces are required 416 result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); 417 return false; 418 } 419 } 420 421 // Check for parenthesis 422 bool parenthesisExistInString = (guidString.IndexOf('(', 0) >= 0); 423 424 if (parenthesisExistInString) { 425 if ((flags & (GuidStyles.AllowParenthesis | GuidStyles.RequireParenthesis)) == 0) { 426 // parenthesis are not allowed 427 result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); 428 return false; 429 } 430 } 431 else { 432 if ((flags & GuidStyles.RequireParenthesis) != 0) { 433 // parenthesis are required 434 result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized"); 435 return false; 436 } 437 } 438 439 try { 440 // let's get on with the parsing 441 if (dashesExistInString) { 442 // Check if it's of the form [{|(]dddddddd-dddd-dddd-dddd-dddddddddddd[}|)] 443 return TryParseGuidWithDashes(guidString, ref result); 444 } 445 else if (bracesExistInString) { 446 // Check if it's of the form {0xdddddddd,0xdddd,0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}} 447 return TryParseGuidWithHexPrefix(guidString, ref result); 448 } 449 else { 450 // Check if it's of the form dddddddddddddddddddddddddddddddd 451 return TryParseGuidWithNoStyle(guidString, ref result); 452 } 453 } 454 catch(IndexOutOfRangeException ex) { 455 result.SetFailure(ParseFailureKind.FormatWithInnerException, "Format_GuidUnrecognized", null, null, ex); 456 return false; 457 } 458 catch (ArgumentException ex) { 459 result.SetFailure(ParseFailureKind.FormatWithInnerException, "Format_GuidUnrecognized", null, null, ex); 460 return false; 461 } 462 } 463 464 465 // Check if it's of the form {0xdddddddd,0xdddd,0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}} TryParseGuidWithHexPrefixSystem.Guid466 private static bool TryParseGuidWithHexPrefix(String guidString, ref GuidResult result) { 467 int numStart = 0; 468 int numLen = 0; 469 470 // Eat all of the whitespace 471 guidString = EatAllWhitespace(guidString); 472 473 // Check for leading '{' 474 if(String.IsNullOrEmpty(guidString) || guidString[0] != '{') { 475 result.SetFailure(ParseFailureKind.Format, "Format_GuidBrace"); 476 return false; 477 } 478 479 // Check for '0x' 480 if(!IsHexPrefix(guidString, 1)) { 481 result.SetFailure(ParseFailureKind.Format, "Format_GuidHexPrefix", "{0xdddddddd, etc}"); 482 return false; 483 } 484 485 // Find the end of this hex number (since it is not fixed length) 486 numStart = 3; 487 numLen = guidString.IndexOf(',', numStart) - numStart; 488 if(numLen <= 0) { 489 result.SetFailure(ParseFailureKind.Format, "Format_GuidComma"); 490 return false; 491 } 492 493 494 if (!StringToInt(guidString.Substring(numStart, numLen) /*first DWORD*/, -1, ParseNumbers.IsTight, out result.parsedGuid._a, ref result)) 495 return false; 496 497 // Check for '0x' 498 if(!IsHexPrefix(guidString, numStart+numLen+1)) { 499 result.SetFailure(ParseFailureKind.Format, "Format_GuidHexPrefix", "{0xdddddddd, 0xdddd, etc}"); 500 return false; 501 } 502 // +3 to get by ',0x' 503 numStart = numStart + numLen + 3; 504 numLen = guidString.IndexOf(',', numStart) - numStart; 505 if(numLen <= 0) { 506 result.SetFailure(ParseFailureKind.Format, "Format_GuidComma"); 507 return false; 508 } 509 510 // Read in the number 511 if (!StringToShort(guidString.Substring(numStart, numLen) /*first DWORD*/, -1, ParseNumbers.IsTight, out result.parsedGuid._b, ref result)) 512 return false; 513 // Check for '0x' 514 if(!IsHexPrefix(guidString, numStart+numLen+1)) { 515 result.SetFailure(ParseFailureKind.Format, "Format_GuidHexPrefix", "{0xdddddddd, 0xdddd, 0xdddd, etc}"); 516 return false; 517 } 518 // +3 to get by ',0x' 519 numStart = numStart + numLen + 3; 520 numLen = guidString.IndexOf(',', numStart) - numStart; 521 if(numLen <= 0) { 522 result.SetFailure(ParseFailureKind.Format, "Format_GuidComma"); 523 return false; 524 } 525 526 // Read in the number 527 if (!StringToShort(guidString.Substring(numStart, numLen) /*first DWORD*/, -1, ParseNumbers.IsTight, out result.parsedGuid._c, ref result)) 528 return false; 529 530 // Check for '{' 531 if(guidString.Length <= numStart+numLen+1 || guidString[numStart+numLen+1] != '{') { 532 result.SetFailure(ParseFailureKind.Format, "Format_GuidBrace"); 533 return false; 534 } 535 536 // Prepare for loop 537 numLen++; 538 byte[] bytes = new byte[8]; 539 540 for(int i = 0; i < 8; i++) 541 { 542 // Check for '0x' 543 if(!IsHexPrefix(guidString, numStart+numLen+1)) { 544 result.SetFailure(ParseFailureKind.Format, "Format_GuidHexPrefix", "{... { ... 0xdd, ...}}"); 545 return false; 546 } 547 548 // +3 to get by ',0x' or '{0x' for first case 549 numStart = numStart + numLen + 3; 550 551 // Calculate number length 552 if(i < 7) // first 7 cases 553 { 554 numLen = guidString.IndexOf(',', numStart) - numStart; 555 if(numLen <= 0) { 556 result.SetFailure(ParseFailureKind.Format, "Format_GuidComma"); 557 return false; 558 } 559 } 560 else // last case ends with '}', not ',' 561 { 562 numLen = guidString.IndexOf('}', numStart) - numStart; 563 if(numLen <= 0) { 564 result.SetFailure(ParseFailureKind.Format, "Format_GuidBraceAfterLastNumber"); 565 return false; 566 } 567 } 568 569 // Read in the number 570 uint number = (uint)Convert.ToInt32(guidString.Substring(numStart, numLen),16); 571 // check for overflow 572 if(number > 255) { 573 result.SetFailure(ParseFailureKind.Format, "Overflow_Byte"); 574 return false; 575 } 576 bytes[i] = (byte)number; 577 } 578 579 result.parsedGuid._d = bytes[0]; 580 result.parsedGuid._e = bytes[1]; 581 result.parsedGuid._f = bytes[2]; 582 result.parsedGuid._g = bytes[3]; 583 result.parsedGuid._h = bytes[4]; 584 result.parsedGuid._i = bytes[5]; 585 result.parsedGuid._j = bytes[6]; 586 result.parsedGuid._k = bytes[7]; 587 588 // Check for last '}' 589 if(numStart+numLen+1 >= guidString.Length || guidString[numStart+numLen+1] != '}') { 590 result.SetFailure(ParseFailureKind.Format, "Format_GuidEndBrace"); 591 return false; 592 } 593 594 // Check if we have extra characters at the end 595 if( numStart+numLen+1 != guidString.Length -1) { 596 result.SetFailure(ParseFailureKind.Format, "Format_ExtraJunkAtEnd"); 597 return false; 598 } 599 600 return true; 601 } 602 603 // Check if it's of the form dddddddddddddddddddddddddddddddd TryParseGuidWithNoStyleSystem.Guid604 private static bool TryParseGuidWithNoStyle(String guidString, ref GuidResult result) { 605 int startPos=0; 606 int temp; 607 long templ; 608 int currentPos = 0; 609 610 if(guidString.Length != 32) { 611 result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); 612 return false; 613 } 614 615 for(int i= 0; i< guidString.Length; i++) { 616 char ch = guidString[i]; 617 if(ch >= '0' && ch <= '9') { 618 continue; 619 } 620 else { 621 char upperCaseCh = Char.ToUpper(ch, CultureInfo.InvariantCulture); 622 if(upperCaseCh >= 'A' && upperCaseCh <= 'F') { 623 continue; 624 } 625 } 626 627 result.SetFailure(ParseFailureKind.Format, "Format_GuidInvalidChar"); 628 return false; 629 } 630 631 if (!StringToInt(guidString.Substring(startPos, 8) /*first DWORD*/, -1, ParseNumbers.IsTight, out result.parsedGuid._a, ref result)) 632 return false; 633 634 startPos += 8; 635 if (!StringToShort(guidString.Substring(startPos, 4), -1, ParseNumbers.IsTight, out result.parsedGuid._b, ref result)) 636 return false; 637 638 startPos += 4; 639 if (!StringToShort(guidString.Substring(startPos, 4), -1, ParseNumbers.IsTight, out result.parsedGuid._c, ref result)) 640 return false; 641 642 startPos += 4; 643 if (!StringToInt(guidString.Substring(startPos, 4), -1, ParseNumbers.IsTight, out temp, ref result)) 644 return false; 645 646 startPos += 4; 647 currentPos = startPos; 648 649 if (!StringToLong(guidString, ref currentPos, ParseNumbers.NoSpace, out templ, ref result)) 650 return false; 651 652 if (currentPos - startPos!=12) { 653 result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); 654 return false; 655 } 656 657 result.parsedGuid._d = (byte)(temp>>8); 658 result.parsedGuid._e = (byte)(temp); 659 temp = (int)(templ >> 32); 660 result.parsedGuid._f = (byte)(temp>>8); 661 result.parsedGuid._g = (byte)(temp); 662 temp = (int)(templ); 663 result.parsedGuid._h = (byte)(temp>>24); 664 result.parsedGuid._i = (byte)(temp>>16); 665 result.parsedGuid._j = (byte)(temp>>8); 666 result.parsedGuid._k = (byte)(temp); 667 668 return true; 669 } 670 671 672 // Check if it's of the form [{|(]dddddddd-dddd-dddd-dddd-dddddddddddd[}|)] TryParseGuidWithDashesSystem.Guid673 private static bool TryParseGuidWithDashes(String guidString, ref GuidResult result) { 674 int startPos=0; 675 int temp; 676 long templ; 677 int currentPos = 0; 678 679 // check to see that it's the proper length 680 if (guidString[0]=='{') { 681 if (guidString.Length!=38 || guidString[37]!='}') { 682 result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); 683 return false; 684 } 685 startPos=1; 686 } 687 else if (guidString[0]=='(') { 688 if (guidString.Length!=38 || guidString[37]!=')') { 689 result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); 690 return false; 691 } 692 startPos=1; 693 } 694 else if(guidString.Length != 36) { 695 result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); 696 return false; 697 } 698 699 if (guidString[8+startPos] != '-' || 700 guidString[13+startPos] != '-' || 701 guidString[18+startPos] != '-' || 702 guidString[23+startPos] != '-') { 703 result.SetFailure(ParseFailureKind.Format, "Format_GuidDashes"); 704 return false; 705 } 706 707 currentPos = startPos; 708 if (!StringToInt(guidString, ref currentPos, 8, ParseNumbers.NoSpace, out temp, ref result)) 709 return false; 710 result.parsedGuid._a = temp; 711 ++currentPos; //Increment past the '-'; 712 713 if (!StringToInt(guidString, ref currentPos, 4, ParseNumbers.NoSpace, out temp, ref result)) 714 return false; 715 result.parsedGuid._b = (short)temp; 716 ++currentPos; //Increment past the '-'; 717 718 if (!StringToInt(guidString, ref currentPos, 4, ParseNumbers.NoSpace, out temp, ref result)) 719 return false; 720 result.parsedGuid._c = (short)temp; 721 ++currentPos; //Increment past the '-'; 722 723 if (!StringToInt(guidString, ref currentPos, 4, ParseNumbers.NoSpace, out temp, ref result)) 724 return false; 725 ++currentPos; //Increment past the '-'; 726 startPos=currentPos; 727 728 if (!StringToLong(guidString, ref currentPos, ParseNumbers.NoSpace, out templ, ref result)) 729 return false; 730 731 if (currentPos - startPos != 12) { 732 result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen"); 733 return false; 734 } 735 result.parsedGuid._d = (byte)(temp>>8); 736 result.parsedGuid._e = (byte)(temp); 737 temp = (int)(templ >> 32); 738 result.parsedGuid._f = (byte)(temp>>8); 739 result.parsedGuid._g = (byte)(temp); 740 temp = (int)(templ); 741 result.parsedGuid._h = (byte)(temp>>24); 742 result.parsedGuid._i = (byte)(temp>>16); 743 result.parsedGuid._j = (byte)(temp>>8); 744 result.parsedGuid._k = (byte)(temp); 745 746 return true; 747 } 748 749 750 // 751 // StringToShort, StringToInt, and StringToLong are wrappers around COMUtilNative integer parsing routines; 752 //< 753 754 [System.Security.SecuritySafeCritical] StringToShortSystem.Guid755 private static unsafe bool StringToShort(String str, int requiredLength, int flags, out short result, ref GuidResult parseResult) { 756 return StringToShort(str, null, requiredLength, flags, out result, ref parseResult); 757 } 758 [System.Security.SecuritySafeCritical] StringToShortSystem.Guid759 private static unsafe bool StringToShort(String str, ref int parsePos, int requiredLength, int flags, out short result, ref GuidResult parseResult) { 760 fixed(int * ppos = &parsePos) { 761 return StringToShort(str, ppos, requiredLength, flags, out result, ref parseResult); 762 } 763 } 764 [System.Security.SecurityCritical] StringToShortSystem.Guid765 private static unsafe bool StringToShort(String str, int* parsePos, int requiredLength, int flags, out short result, ref GuidResult parseResult) { 766 result = 0; 767 int x; 768 bool retValue = StringToInt(str, parsePos, requiredLength, flags, out x, ref parseResult); 769 result = (short)x; 770 return retValue; 771 } 772 773 [System.Security.SecuritySafeCritical] StringToIntSystem.Guid774 private static unsafe bool StringToInt(String str, int requiredLength, int flags, out int result, ref GuidResult parseResult) { 775 return StringToInt(str, null, requiredLength, flags, out result, ref parseResult); 776 } 777 [System.Security.SecuritySafeCritical] StringToIntSystem.Guid778 private static unsafe bool StringToInt(String str, ref int parsePos, int requiredLength, int flags, out int result, ref GuidResult parseResult) { 779 fixed(int * ppos = &parsePos) { 780 return StringToInt(str, ppos, requiredLength, flags, out result, ref parseResult); 781 } 782 } 783 [System.Security.SecurityCritical] StringToIntSystem.Guid784 private static unsafe bool StringToInt(String str, int* parsePos, int requiredLength, int flags, out int result, ref GuidResult parseResult) { 785 result = 0; 786 787 int currStart = (parsePos == null) ? 0 : (*parsePos); 788 try { 789 result = ParseNumbers.StringToInt(str, 16, flags, parsePos); 790 } 791 catch (OverflowException ex) { 792 if (parseResult.throwStyle == GuidParseThrowStyle.All) { 793 throw; 794 } 795 else if (parseResult.throwStyle == GuidParseThrowStyle.AllButOverflow) { 796 throw new FormatException(Environment.GetResourceString("Format_GuidUnrecognized"), ex); 797 } 798 else { 799 parseResult.SetFailure(ex); 800 return false; 801 } 802 } 803 catch (Exception ex) { 804 if (parseResult.throwStyle == GuidParseThrowStyle.None) { 805 parseResult.SetFailure(ex); 806 return false; 807 } 808 else { 809 throw; 810 } 811 } 812 813 //If we didn't parse enough characters, there's clearly an error. 814 if (requiredLength != -1 && parsePos != null && (*parsePos) - currStart != requiredLength) { 815 parseResult.SetFailure(ParseFailureKind.Format, "Format_GuidInvalidChar"); 816 return false; 817 } 818 return true; 819 } 820 [System.Security.SecuritySafeCritical] StringToLongSystem.Guid821 private static unsafe bool StringToLong(String str, int flags, out long result, ref GuidResult parseResult) { 822 return StringToLong(str, null, flags, out result, ref parseResult); 823 } 824 [System.Security.SecuritySafeCritical] StringToLongSystem.Guid825 private static unsafe bool StringToLong(String str, ref int parsePos, int flags, out long result, ref GuidResult parseResult) { 826 fixed(int * ppos = &parsePos) { 827 return StringToLong(str, ppos, flags, out result, ref parseResult); 828 } 829 } 830 [System.Security.SecuritySafeCritical] StringToLongSystem.Guid831 private static unsafe bool StringToLong(String str, int* parsePos, int flags, out long result, ref GuidResult parseResult) { 832 result = 0; 833 834 try { 835 result = ParseNumbers.StringToLong(str, 16, flags, parsePos); 836 } 837 catch (OverflowException ex) { 838 if (parseResult.throwStyle == GuidParseThrowStyle.All) { 839 throw; 840 } 841 else if (parseResult.throwStyle == GuidParseThrowStyle.AllButOverflow) { 842 throw new FormatException(Environment.GetResourceString("Format_GuidUnrecognized"), ex); 843 } 844 else { 845 parseResult.SetFailure(ex); 846 return false; 847 } 848 } 849 catch (Exception ex) { 850 if (parseResult.throwStyle == GuidParseThrowStyle.None) { 851 parseResult.SetFailure(ex); 852 return false; 853 } 854 else { 855 throw; 856 } 857 } 858 return true; 859 } 860 861 EatAllWhitespaceSystem.Guid862 private static String EatAllWhitespace(String str) 863 { 864 int newLength = 0; 865 char[] chArr = new char[str.Length]; 866 char curChar; 867 868 // Now get each char from str and if it is not whitespace add it to chArr 869 for(int i = 0; i < str.Length; i++) 870 { 871 curChar = str[i]; 872 if(!Char.IsWhiteSpace(curChar)) 873 { 874 chArr[newLength++] = curChar; 875 } 876 } 877 878 // Return a new string based on chArr 879 return new String(chArr, 0, newLength); 880 } 881 IsHexPrefixSystem.Guid882 private static bool IsHexPrefix(String str, int i) 883 { 884 if(str.Length > i+1 && str[i] == '0' && (Char.ToLower(str[i+1], CultureInfo.InvariantCulture) == 'x')) 885 return true; 886 else 887 return false; 888 } 889 890 891 // Returns an unsigned byte array containing the GUID. ToByteArraySystem.Guid892 public byte[] ToByteArray() 893 { 894 byte[] g = new byte[16]; 895 896 g[0] = (byte)(_a); 897 g[1] = (byte)(_a >> 8); 898 g[2] = (byte)(_a >> 16); 899 g[3] = (byte)(_a >> 24); 900 g[4] = (byte)(_b); 901 g[5] = (byte)(_b >> 8); 902 g[6] = (byte)(_c); 903 g[7] = (byte)(_c >> 8); 904 g[8] = _d; 905 g[9] = _e; 906 g[10] = _f; 907 g[11] = _g; 908 g[12] = _h; 909 g[13] = _i; 910 g[14] = _j; 911 g[15] = _k; 912 913 return g; 914 } 915 916 917 // Returns the guid in "registry" format. ToStringSystem.Guid918 public override String ToString() 919 { 920 return ToString("D",null); 921 } 922 GetHashCodeSystem.Guid923 public override int GetHashCode() 924 { 925 return _a ^ (((int)_b << 16) | (int)(ushort)_c) ^ (((int)_f << 24) | _k); 926 } 927 928 // Returns true if and only if the guid represented 929 // by o is the same as this instance. EqualsSystem.Guid930 public override bool Equals(Object o) 931 { 932 Guid g; 933 // Check that o is a Guid first 934 if(o == null || !(o is Guid)) 935 return false; 936 else g = (Guid) o; 937 938 // Now compare each of the elements 939 if(g._a != _a) 940 return false; 941 if(g._b != _b) 942 return false; 943 if(g._c != _c) 944 return false; 945 if (g._d != _d) 946 return false; 947 if (g._e != _e) 948 return false; 949 if (g._f != _f) 950 return false; 951 if (g._g != _g) 952 return false; 953 if (g._h != _h) 954 return false; 955 if (g._i != _i) 956 return false; 957 if (g._j != _j) 958 return false; 959 if (g._k != _k) 960 return false; 961 962 return true; 963 } 964 EqualsSystem.Guid965 public bool Equals(Guid g) 966 { 967 // Now compare each of the elements 968 if(g._a != _a) 969 return false; 970 if(g._b != _b) 971 return false; 972 if(g._c != _c) 973 return false; 974 if (g._d != _d) 975 return false; 976 if (g._e != _e) 977 return false; 978 if (g._f != _f) 979 return false; 980 if (g._g != _g) 981 return false; 982 if (g._h != _h) 983 return false; 984 if (g._i != _i) 985 return false; 986 if (g._j != _j) 987 return false; 988 if (g._k != _k) 989 return false; 990 991 return true; 992 } 993 GetResultSystem.Guid994 private int GetResult(uint me, uint them) { 995 if (me<them) { 996 return -1; 997 } 998 return 1; 999 } 1000 CompareToSystem.Guid1001 public int CompareTo(Object value) { 1002 if (value == null) { 1003 return 1; 1004 } 1005 if (!(value is Guid)) { 1006 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeGuid")); 1007 } 1008 Guid g = (Guid)value; 1009 1010 if (g._a!=this._a) { 1011 return GetResult((uint)this._a, (uint)g._a); 1012 } 1013 1014 if (g._b!=this._b) { 1015 return GetResult((uint)this._b, (uint)g._b); 1016 } 1017 1018 if (g._c!=this._c) { 1019 return GetResult((uint)this._c, (uint)g._c); 1020 } 1021 1022 if (g._d!=this._d) { 1023 return GetResult((uint)this._d, (uint)g._d); 1024 } 1025 1026 if (g._e!=this._e) { 1027 return GetResult((uint)this._e, (uint)g._e); 1028 } 1029 1030 if (g._f!=this._f) { 1031 return GetResult((uint)this._f, (uint)g._f); 1032 } 1033 1034 if (g._g!=this._g) { 1035 return GetResult((uint)this._g, (uint)g._g); 1036 } 1037 1038 if (g._h!=this._h) { 1039 return GetResult((uint)this._h, (uint)g._h); 1040 } 1041 1042 if (g._i!=this._i) { 1043 return GetResult((uint)this._i, (uint)g._i); 1044 } 1045 1046 if (g._j!=this._j) { 1047 return GetResult((uint)this._j, (uint)g._j); 1048 } 1049 1050 if (g._k!=this._k) { 1051 return GetResult((uint)this._k, (uint)g._k); 1052 } 1053 1054 return 0; 1055 } 1056 1057 #if GENERICS_WORK CompareToSystem.Guid1058 public int CompareTo(Guid value) 1059 { 1060 if (value._a!=this._a) { 1061 return GetResult((uint)this._a, (uint)value._a); 1062 } 1063 1064 if (value._b!=this._b) { 1065 return GetResult((uint)this._b, (uint)value._b); 1066 } 1067 1068 if (value._c!=this._c) { 1069 return GetResult((uint)this._c, (uint)value._c); 1070 } 1071 1072 if (value._d!=this._d) { 1073 return GetResult((uint)this._d, (uint)value._d); 1074 } 1075 1076 if (value._e!=this._e) { 1077 return GetResult((uint)this._e, (uint)value._e); 1078 } 1079 1080 if (value._f!=this._f) { 1081 return GetResult((uint)this._f, (uint)value._f); 1082 } 1083 1084 if (value._g!=this._g) { 1085 return GetResult((uint)this._g, (uint)value._g); 1086 } 1087 1088 if (value._h!=this._h) { 1089 return GetResult((uint)this._h, (uint)value._h); 1090 } 1091 1092 if (value._i!=this._i) { 1093 return GetResult((uint)this._i, (uint)value._i); 1094 } 1095 1096 if (value._j!=this._j) { 1097 return GetResult((uint)this._j, (uint)value._j); 1098 } 1099 1100 if (value._k!=this._k) { 1101 return GetResult((uint)this._k, (uint)value._k); 1102 } 1103 1104 return 0; 1105 } 1106 #endif // GENERICS_WORK 1107 operator ==System.Guid1108 public static bool operator ==(Guid a, Guid b) 1109 { 1110 // Now compare each of the elements 1111 if(a._a != b._a) 1112 return false; 1113 if(a._b != b._b) 1114 return false; 1115 if(a._c != b._c) 1116 return false; 1117 if(a._d != b._d) 1118 return false; 1119 if(a._e != b._e) 1120 return false; 1121 if(a._f != b._f) 1122 return false; 1123 if(a._g != b._g) 1124 return false; 1125 if(a._h != b._h) 1126 return false; 1127 if(a._i != b._i) 1128 return false; 1129 if(a._j != b._j) 1130 return false; 1131 if(a._k != b._k) 1132 return false; 1133 1134 return true; 1135 } 1136 operator !=System.Guid1137 public static bool operator !=(Guid a, Guid b) 1138 { 1139 return !(a == b); 1140 } 1141 #if !MONO 1142 // This will create a new guid. Since we've now decided that constructors should 0-init, 1143 // we need a method that allows users to create a guid. 1144 [System.Security.SecuritySafeCritical] // auto-generated NewGuidSystem.Guid1145 public static Guid NewGuid() { 1146 // CoCreateGuid should never return Guid.Empty, since it attempts to maintain some 1147 // uniqueness guarantees. It should also never return a known GUID, but it's unclear 1148 // how extensively it checks for known values. 1149 Contract.Ensures(Contract.Result<Guid>() != Guid.Empty); 1150 1151 Guid guid; 1152 Marshal.ThrowExceptionForHR(Win32Native.CoCreateGuid(out guid), new IntPtr(-1)); 1153 return guid; 1154 } 1155 #endif ToStringSystem.Guid1156 public String ToString(String format) { 1157 return ToString(format, null); 1158 } 1159 HexToCharSystem.Guid1160 private static char HexToChar(int a) 1161 { 1162 a = a & 0xf; 1163 return (char) ((a > 9) ? a - 10 + 0x61 : a + 0x30); 1164 } 1165 1166 [System.Security.SecurityCritical] HexsToCharsSystem.Guid1167 unsafe private static int HexsToChars(char* guidChars, int offset, int a, int b) 1168 { 1169 return HexsToChars(guidChars, offset, a, b, false); 1170 } 1171 1172 [System.Security.SecurityCritical] HexsToCharsSystem.Guid1173 unsafe private static int HexsToChars(char* guidChars, int offset, int a, int b, bool hex) 1174 { 1175 if (hex) { 1176 guidChars[offset++] = '0'; 1177 guidChars[offset++] = 'x'; 1178 } 1179 guidChars[offset++] = HexToChar(a>>4); 1180 guidChars[offset++] = HexToChar(a); 1181 if (hex) { 1182 guidChars[offset++] = ','; 1183 guidChars[offset++] = '0'; 1184 guidChars[offset++] = 'x'; 1185 } 1186 guidChars[offset++] = HexToChar(b>>4); 1187 guidChars[offset++] = HexToChar(b); 1188 return offset; 1189 } 1190 1191 // IFormattable interface 1192 // We currently ignore provider 1193 [System.Security.SecuritySafeCritical] ToStringSystem.Guid1194 public String ToString(String format, IFormatProvider provider) 1195 { 1196 if (format == null || format.Length == 0) 1197 format = "D"; 1198 1199 string guidString; 1200 int offset = 0; 1201 bool dash = true; 1202 bool hex = false; 1203 1204 if( format.Length != 1) { 1205 // all acceptable format strings are of length 1 1206 throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification")); 1207 } 1208 1209 char formatCh = format[0]; 1210 if (formatCh == 'D' || formatCh == 'd') { 1211 guidString = string.FastAllocateString(36); 1212 } 1213 else if (formatCh == 'N' || formatCh == 'n') { 1214 guidString = string.FastAllocateString(32); 1215 dash = false; 1216 } 1217 else if (formatCh == 'B' || formatCh == 'b') { 1218 guidString = string.FastAllocateString(38); 1219 unsafe { 1220 fixed (char* guidChars = guidString) { 1221 guidChars[offset++] = '{'; 1222 guidChars[37] = '}'; 1223 } 1224 } 1225 } 1226 else if (formatCh == 'P' || formatCh == 'p') { 1227 guidString = string.FastAllocateString(38); 1228 unsafe { 1229 fixed (char* guidChars = guidString) { 1230 guidChars[offset++] = '('; 1231 guidChars[37] = ')'; 1232 } 1233 } 1234 } 1235 else if (formatCh == 'X' || formatCh == 'x') { 1236 guidString = string.FastAllocateString(68); 1237 unsafe { 1238 fixed (char* guidChars = guidString) { 1239 guidChars[offset++] = '{'; 1240 guidChars[67] = '}'; 1241 } 1242 } 1243 dash = false; 1244 hex = true; 1245 } 1246 else { 1247 throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification")); 1248 } 1249 1250 unsafe { 1251 fixed (char* guidChars = guidString) { 1252 if (hex) { 1253 // {0xdddddddd,0xdddd,0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}} 1254 guidChars[offset++] = '0'; 1255 guidChars[offset++] = 'x'; 1256 offset = HexsToChars(guidChars, offset, _a >> 24, _a >> 16); 1257 offset = HexsToChars(guidChars, offset, _a >> 8, _a); 1258 guidChars[offset++] = ','; 1259 guidChars[offset++] = '0'; 1260 guidChars[offset++] = 'x'; 1261 offset = HexsToChars(guidChars, offset, _b >> 8, _b); 1262 guidChars[offset++] = ','; 1263 guidChars[offset++] = '0'; 1264 guidChars[offset++] = 'x'; 1265 offset = HexsToChars(guidChars, offset, _c >> 8, _c); 1266 guidChars[offset++] = ','; 1267 guidChars[offset++] = '{'; 1268 offset = HexsToChars(guidChars, offset, _d, _e, true); 1269 guidChars[offset++] = ','; 1270 offset = HexsToChars(guidChars, offset, _f, _g, true); 1271 guidChars[offset++] = ','; 1272 offset = HexsToChars(guidChars, offset, _h, _i, true); 1273 guidChars[offset++] = ','; 1274 offset = HexsToChars(guidChars, offset, _j, _k, true); 1275 guidChars[offset++] = '}'; 1276 } 1277 else { 1278 // [{|(]dddddddd[-]dddd[-]dddd[-]dddd[-]dddddddddddd[}|)] 1279 offset = HexsToChars(guidChars, offset, _a >> 24, _a >> 16); 1280 offset = HexsToChars(guidChars, offset, _a >> 8, _a); 1281 if (dash) guidChars[offset++] = '-'; 1282 offset = HexsToChars(guidChars, offset, _b >> 8, _b); 1283 if (dash) guidChars[offset++] = '-'; 1284 offset = HexsToChars(guidChars, offset, _c >> 8, _c); 1285 if (dash) guidChars[offset++] = '-'; 1286 offset = HexsToChars(guidChars, offset, _d, _e); 1287 if (dash) guidChars[offset++] = '-'; 1288 offset = HexsToChars(guidChars, offset, _f, _g); 1289 offset = HexsToChars(guidChars, offset, _h, _i); 1290 offset = HexsToChars(guidChars, offset, _j, _k); 1291 } 1292 } 1293 } 1294 return guidString; 1295 } 1296 } 1297 } 1298