1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Diagnostics; 6 using System.ComponentModel; 7 using System.Runtime.InteropServices; 8 using System.Globalization; 9 using System.Reflection; 10 using System.ComponentModel.Design.Serialization; 11 12 namespace System.Management 13 { 14 /// <summary> 15 /// <para>Provides a wrapper for parsing and building paths to WMI objects.</para> 16 /// </summary> 17 /// <example> 18 /// <code lang='C#'>using System; 19 /// using System.Management; 20 /// 21 /// // This sample displays all properties in a ManagementPath object. 22 /// 23 /// class Sample_ManagementPath 24 /// { 25 /// public static int Main(string[] args) { 26 /// ManagementPath path = new ManagementPath( "\\\\MyServer\\MyNamespace:Win32_logicaldisk='c:'"); 27 /// 28 /// // Results of full path parsing 29 /// Console.WriteLine("Path: " + path.Path); 30 /// Console.WriteLine("RelativePath: " + path.RelativePath); 31 /// Console.WriteLine("Server: " + path.Server); 32 /// Console.WriteLine("NamespacePath: " + path.NamespacePath); 33 /// Console.WriteLine("ClassName: " + path.ClassName); 34 /// Console.WriteLine("IsClass: " + path.IsClass); 35 /// Console.WriteLine("IsInstance: " + path.IsInstance); 36 /// Console.WriteLine("IsSingleton: " + path.IsSingleton); 37 /// 38 /// // Change a portion of the full path 39 /// path.Server = "AnotherServer"; 40 /// Console.WriteLine("New Path: " + path.Path); 41 /// return 0; 42 /// } 43 /// } 44 /// </code> 45 /// <code lang='VB'>Imports System 46 /// Imports System.Management 47 /// 48 /// 'This sample displays all properties in a ManagementPath object. 49 /// Class Sample_ManagementPath Overloads 50 /// Public Shared Function Main(args() As String) As Integer 51 /// Dim path As _ New 52 /// ManagementPath("\\MyServer\MyNamespace:Win32_LogicalDisk='c:'") 53 /// 54 /// ' Results of full path parsing 55 /// Console.WriteLine("Path: " & path.Path) 56 /// Console.WriteLine("RelativePath: " & path.RelativePath) 57 /// Console.WriteLine("Server: " & path.Server) 58 /// Console.WriteLine("NamespacePath: " & path.NamespacePath) 59 /// Console.WriteLine("ClassName: " & path.ClassName) 60 /// Console.WriteLine("IsClass: " & path.IsClass) 61 /// Console.WriteLine("IsInstance: " & path.IsInstance) 62 /// Console.WriteLine("IsSingleton: " & path.IsSingleton) 63 /// 64 /// ' Change a portion of the full path 65 /// path.Server= "AnotherServer" 66 /// Console.WriteLine("New Path: " & path.Path) 67 /// Return 0 68 /// End Function 69 /// End Class 70 /// </code> 71 /// </example> 72 [TypeConverter(typeof(ManagementPathConverter ))] 73 public class ManagementPath : ICloneable 74 { 75 private static ManagementPath defaultPath = new ManagementPath("//./root/cimv2"); 76 77 //Used to minimize the cases in which new wbemPath (WMI object path parser) objects need to be constructed 78 //This is done for performance reasons. 79 private bool isWbemPathShared = false; 80 81 internal event IdentifierChangedEventHandler IdentifierChanged; 82 83 //Fires IdentifierChanged event FireIdentifierChanged()84 private void FireIdentifierChanged() 85 { 86 if (IdentifierChanged != null) 87 IdentifierChanged(this, null); 88 } 89 90 //internal factory 91 /// <summary> 92 /// Internal static "factory" method for making a new ManagementPath 93 /// from the system property of a WMI object 94 /// </summary> 95 /// <param name="wbemObject">The WMI object whose __PATH property will 96 /// be used to supply the returned object</param> GetManagementPath( IWbemClassObjectFreeThreaded wbemObject)97 internal static string GetManagementPath ( 98 IWbemClassObjectFreeThreaded wbemObject) 99 { 100 string path = null; 101 int status = (int)ManagementStatus.Failed; 102 103 if (null != wbemObject) 104 { 105 int dummy1 = 0, dummy2 = 0; 106 object val = null; 107 status = wbemObject.Get_ ("__PATH", 0, ref val, ref dummy1, ref dummy2); 108 if ((status < 0) || (val == System.DBNull.Value)) 109 { 110 //try to get the relpath instead 111 status = wbemObject.Get_ ("__RELPATH", 0, ref val, ref dummy1, ref dummy2); 112 if (status < 0) 113 { 114 if ((status & 0xfffff000) == 0x80041000) 115 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 116 else 117 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 118 } 119 } 120 121 if (System.DBNull.Value == val) 122 path = null; 123 else 124 path = (string)val; 125 } 126 127 return path; 128 } 129 130 //Used internally to check whether a string passed in as a namespace is indeed syntactically correct 131 //for a namespace (e.g. either has "\" or "/" in it or is the special case of "root") 132 //This doesn't check for the existance of that namespace, nor does it guarrantee correctness. IsValidNamespaceSyntax(string nsPath)133 internal static bool IsValidNamespaceSyntax(string nsPath) 134 { 135 if (nsPath.Length != 0) 136 { 137 // Any path separators present? 138 char[] pathSeparators = { '\\', '/' }; 139 if (nsPath.IndexOfAny(pathSeparators) == -1) 140 { 141 // No separators. The only valid path is "root". 142 if (String.Compare("root", nsPath, StringComparison.OrdinalIgnoreCase) != 0) 143 return false; 144 } 145 } 146 147 return true; 148 } 149 150 _Clone(ManagementPath path)151 internal static ManagementPath _Clone(ManagementPath path) 152 { 153 return ManagementPath._Clone(path, null); 154 } 155 _Clone(ManagementPath path, IdentifierChangedEventHandler handler)156 internal static ManagementPath _Clone(ManagementPath path, IdentifierChangedEventHandler handler) 157 { 158 ManagementPath pathTmp = new ManagementPath(); 159 160 // Wire up change handler chain. Use supplied handler, if specified; 161 // otherwise, default to that of the path argument. 162 if (handler != null) 163 pathTmp.IdentifierChanged = handler; 164 165 // Assign ManagementPath IWbemPath to this.wmiPath. 166 // Optimization for performance : As long as the path is only read, we share this interface. 167 // On the first write, a private copy will be needed; 168 // isWbemPathShared signals ManagementPath to create such a copy at write-time. 169 if (path != null && path.wmiPath != null) 170 { 171 pathTmp.wmiPath = path.wmiPath; 172 pathTmp.isWbemPathShared = path.isWbemPathShared = true; 173 } 174 175 return pathTmp; 176 } 177 178 /// <overload> 179 /// Initializes a new instance 180 /// of the <see cref='System.Management.ManagementPath'/> class. 181 /// </overload> 182 /// <summary> 183 /// <para> Initializes a new instance of the <see cref='System.Management.ManagementPath'/> class that is empty. This is the default constructor.</para> 184 /// </summary> ManagementPath()185 public ManagementPath () : this ((string) null) {} 186 187 /// <summary> 188 /// <para>Initializes a new instance of the <see cref='System.Management.ManagementPath'/> class for the given path.</para> 189 /// </summary> 190 /// <param name='path'> The object path. </param> ManagementPath(string path)191 public ManagementPath(string path) 192 { 193 if ((null != path) && (0 < path.Length)) 194 wmiPath = CreateWbemPath(path); 195 } 196 197 /// <summary> 198 /// <para>Returns the full object path as the string representation.</para> 199 /// </summary> 200 /// <returns> 201 /// A string containing the full object 202 /// path represented by this object. This value is equivalent to the value of the 203 /// <see cref='System.Management.ManagementPath.Path'/> property. 204 /// </returns> ToString()205 public override string ToString () 206 { 207 return this.Path; 208 } 209 210 /// <summary> 211 /// <para>Returns a copy of the <see cref='System.Management.ManagementPath'/>.</para> 212 /// </summary> 213 /// <returns> 214 /// The cloned object. 215 /// </returns> Clone()216 public ManagementPath Clone () 217 { 218 return new ManagementPath (Path); 219 } 220 221 /// <summary> 222 /// Standard Clone returns a copy of this ManagementPath as a generic "Object" type 223 /// </summary> 224 /// <returns> 225 /// The cloned object. 226 /// </returns> ICloneable.Clone()227 object ICloneable.Clone () 228 { 229 return Clone (); 230 } 231 232 /// <summary> 233 /// <para>Gets or sets the default scope path used when no scope is specified. 234 /// The default scope is /-/ \\.\root\cimv2, and can be changed by setting this property.</para> 235 /// </summary> 236 /// <value> 237 /// <para>By default the scope value is /-/ \\.\root\cimv2, or a different scope path if 238 /// the default was changed.</para> 239 /// </value> 240 public static ManagementPath DefaultPath 241 { 242 get { return ManagementPath.defaultPath; } 243 set { ManagementPath.defaultPath = value; } 244 } 245 246 //private members 247 private IWbemPath wmiPath; 248 CreateWbemPath(string path)249 private IWbemPath CreateWbemPath(string path) 250 { 251 IWbemPath wbemPath = (IWbemPath)MTAHelper.CreateInMTA(typeof(WbemDefPath));//new WbemDefPath(); 252 SetWbemPath(wbemPath, path); 253 return wbemPath; 254 } 255 SetWbemPath(string path)256 private void SetWbemPath(string path) 257 { 258 // Test/utilize isWbemPathShared *only* on public + internal members! 259 if (wmiPath == null) 260 wmiPath = CreateWbemPath(path); 261 else 262 SetWbemPath(wmiPath, path); 263 } 264 SetWbemPath(IWbemPath wbemPath, string path)265 private static void SetWbemPath(IWbemPath wbemPath, string path) 266 { 267 if (null != wbemPath) 268 { 269 uint flags = (uint) tag_WBEM_PATH_CREATE_FLAG.WBEMPATH_CREATE_ACCEPT_ALL; 270 271 //For now we have to special-case the "root" namespace - 272 // this is because in the case of "root", the path parser cannot tell whether 273 // this is a namespace name or a class name 274 if (String.Compare(path, "root", StringComparison.OrdinalIgnoreCase) == 0) 275 flags = flags | (uint) tag_WBEM_PATH_CREATE_FLAG.WBEMPATH_TREAT_SINGLE_IDENT_AS_NS; 276 277 int status = wbemPath.SetText_(flags, path); 278 279 if (status < 0) 280 { 281 if ((status & 0xfffff000) == 0x80041000) 282 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 283 else 284 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 285 } 286 } 287 } 288 GetWbemPath()289 private string GetWbemPath() 290 { 291 return GetWbemPath(this.wmiPath); 292 } 293 GetWbemPath(IWbemPath wbemPath)294 private static string GetWbemPath(IWbemPath wbemPath) 295 { 296 String pathStr = String.Empty; 297 298 if (null != wbemPath) 299 { 300 // Requesting the path from a parser which has 301 // been only given a relative path results in an incorrect 302 // value being returned (e.g. \\.\win32_logicaldisk). To work 303 // around this we check if there are any namespaces, 304 // and if not ask for the relative path instead. 305 int flags = (int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_TOO; 306 uint nCount = 0; 307 308 int status = (int)ManagementStatus.NoError; 309 310 status = wbemPath.GetNamespaceCount_(out nCount); 311 312 if (status >= 0) 313 { 314 if (0 == nCount) 315 flags = (int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_RELATIVE_ONLY; 316 317 // Get the space we need to reserve 318 uint bufLen = 0; 319 320 status = wbemPath.GetText_(flags, ref bufLen, null); 321 322 if (status >= 0 && 0 < bufLen) 323 { 324 pathStr = new String ('0', (int) bufLen-1); 325 status = wbemPath.GetText_(flags, ref bufLen, pathStr); 326 } 327 } 328 329 if (status < 0) 330 { 331 if (status == (int)tag_WBEMSTATUS.WBEM_E_INVALID_PARAMETER) 332 { 333 // Interpret as unspecified - return "" 334 } 335 336 else if ((status & 0xfffff000) == 0x80041000) 337 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 338 else 339 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 340 } 341 } 342 343 return pathStr; 344 } 345 ClearKeys(bool setAsSingleton)346 private void ClearKeys (bool setAsSingleton) 347 { 348 // Test/utilize isWbemPathShared *only* on public + internal members! 349 int status = (int)ManagementStatus.NoError; 350 351 try 352 { 353 if (null != wmiPath) 354 { 355 IWbemPathKeyList keyList = null; 356 status = wmiPath.GetKeyList_(out keyList); 357 358 if (null != keyList) 359 { 360 status = keyList.RemoveAllKeys_(0); 361 if ((status & 0x80000000) == 0) 362 { 363 sbyte bSingleton = (setAsSingleton) ? (sbyte)(-1) : (sbyte)0; 364 status = keyList.MakeSingleton_(bSingleton); 365 FireIdentifierChanged (); 366 } 367 } 368 } 369 } 370 catch (COMException e) 371 { 372 ManagementException.ThrowWithExtendedInfo(e); 373 } 374 375 if ((status & 0xfffff000) == 0x80041000) 376 { 377 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 378 } 379 else if ((status & 0x80000000) != 0) 380 { 381 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 382 } 383 } 384 385 internal bool IsEmpty 386 { 387 get 388 { 389 return (Path.Length == 0 ) ; 390 } 391 } 392 393 394 // 395 // Methods 396 // 397 398 /// <summary> 399 /// <para> Sets the path as a new class path. This means that the path must have 400 /// a class name but not key values.</para> 401 /// </summary> SetAsClass()402 public void SetAsClass () 403 { 404 if (IsClass || IsInstance) 405 { 406 // Check if this IWbemPath is shared among multiple managed objects. 407 // With this write, it will have to maintain its own copy. 408 if (isWbemPathShared) 409 { 410 wmiPath = CreateWbemPath(this.GetWbemPath()); 411 isWbemPathShared = false; 412 } 413 414 ClearKeys (false); 415 } 416 else 417 throw new ManagementException (ManagementStatus.InvalidOperation, null, null); 418 } 419 420 /// <summary> 421 /// <para> Sets the path as a new singleton object path. This means that it is a path to an instance but 422 /// there are no key values.</para> 423 /// </summary> SetAsSingleton()424 public void SetAsSingleton () 425 { 426 if (IsClass || IsInstance) 427 { 428 // Check if this IWbemPath is shared among multiple managed objects. 429 // With this write, it will have to maintain its own copy. 430 if (isWbemPathShared) 431 { 432 wmiPath = CreateWbemPath(this.GetWbemPath()); 433 isWbemPathShared = false; 434 } 435 436 ClearKeys (true); 437 } 438 else 439 throw new ManagementException (ManagementStatus.InvalidOperation, null, null); 440 } 441 442 // 443 // Properties 444 // 445 446 /// <summary> 447 /// <para> Gets or sets the string representation of the full path in the object.</para> 448 /// </summary> 449 /// <value> 450 /// <para>A string containing the full path 451 /// represented in this object.</para> 452 /// </value> 453 [RefreshProperties(RefreshProperties.All)] 454 public string Path 455 { 456 get 457 { 458 return this.GetWbemPath(); 459 } 460 set 461 { 462 try 463 { 464 // Before overwriting, check it's OK 465 // Note, we've never done such validation, should we? 466 // 467 // Check if this IWbemPath is shared among multiple managed objects. 468 // With this write, it will have to maintain its own copy. 469 if (isWbemPathShared) 470 { 471 wmiPath = CreateWbemPath(this.GetWbemPath()); 472 isWbemPathShared = false; 473 } 474 475 this.SetWbemPath(value); 476 } 477 catch 478 { 479 throw new ArgumentOutOfRangeException ("value"); 480 } 481 FireIdentifierChanged(); 482 } 483 } 484 485 /// <summary> 486 /// <para> Gets or sets the relative path: class name and keys only.</para> 487 /// </summary> 488 /// <value> 489 /// A string containing the relative 490 /// path (not including the server and namespace portions) represented in this 491 /// object. 492 /// </value> 493 [RefreshProperties(RefreshProperties.All)] 494 public string RelativePath 495 { 496 get 497 { 498 String pathStr = String.Empty; 499 500 if (null != wmiPath) 501 { 502 // Get the space we need to reserve 503 uint bufLen = 0; 504 int status = wmiPath.GetText_( 505 (int) tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_RELATIVE_ONLY, 506 ref bufLen, 507 null); 508 509 if (status >= 0 && 0 < bufLen) 510 { 511 pathStr = new String ('0', (int) bufLen-1); 512 status = wmiPath.GetText_( 513 (int) tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_RELATIVE_ONLY, 514 ref bufLen, 515 pathStr); 516 } 517 518 if (status < 0) 519 { 520 if (status == (int)tag_WBEMSTATUS.WBEM_E_INVALID_PARAMETER) 521 { 522 // Interpret as unspecified - return "" 523 } 524 else if ((status & 0xfffff000) == 0x80041000) 525 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 526 else 527 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 528 } 529 } 530 531 return pathStr; 532 } 533 534 set 535 { 536 try 537 { 538 // No need for isWbemPathShared here since internal SetRelativePath 539 // always creates a new copy. 540 SetRelativePath (value); 541 } 542 catch (COMException) 543 { 544 throw new ArgumentOutOfRangeException ("value"); 545 } 546 FireIdentifierChanged(); 547 } 548 } 549 SetRelativePath(string relPath)550 internal void SetRelativePath (string relPath) 551 { 552 // No need for isWbemPathShared here since internal SetRelativePath 553 // always creates a new copy. 554 ManagementPath newPath = new ManagementPath (relPath); 555 newPath.NamespacePath = this.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY); 556 newPath.Server = this.Server; 557 wmiPath = newPath.wmiPath; 558 } 559 560 //Used to update the relative path when the user changes any key properties UpdateRelativePath(string relPath)561 internal void UpdateRelativePath(string relPath) 562 { 563 if (relPath == null) 564 return; 565 566 //Get the server & namespace part from the existing path, and concatenate the given relPath. 567 //NOTE : we need to do this because IWbemPath doesn't have a function to set the relative path alone... 568 string newPath = String.Empty; 569 string nsPath = this.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY); 570 571 if (nsPath.Length>0 ) 572 newPath = String.Concat(nsPath, ":", relPath); 573 else 574 newPath = relPath; 575 576 // Check if this IWbemPath is shared among multiple managed objects. 577 // With this write, it will have to maintain its own copy. 578 if (isWbemPathShared) 579 { 580 wmiPath = CreateWbemPath(this.GetWbemPath()); 581 isWbemPathShared = false; 582 } 583 584 this.SetWbemPath(newPath); 585 } 586 587 588 /// <summary> 589 /// <para>Gets or sets the server part of the path.</para> 590 /// </summary> 591 /// <value> 592 /// A string containing the server name 593 /// from the path represented in this object. 594 /// </value> 595 [RefreshProperties(RefreshProperties.All)] 596 public string Server 597 { 598 get 599 { 600 String pathStr = String.Empty; 601 602 if (null != wmiPath) 603 { 604 605 uint uLen = 0; 606 int status = wmiPath.GetServer_(ref uLen, null); 607 608 if (status >= 0 && 0 < uLen) 609 { 610 pathStr = new String ('0', (int) uLen-1); 611 status = wmiPath.GetServer_(ref uLen, pathStr); 612 } 613 614 if (status < 0) 615 { 616 if (status == (int)tag_WBEMSTATUS.WBEM_E_NOT_AVAILABLE) 617 { 618 // Interpret as unspecified - return "" 619 } 620 else if ((status & 0xfffff000) == 0x80041000) 621 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 622 else 623 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 624 } 625 } 626 627 return pathStr; 628 } 629 set 630 { 631 String oldValue = Server; 632 633 // Only set if changed 634 if (0 != String.Compare(oldValue,value,StringComparison.OrdinalIgnoreCase)) 635 { 636 if (null == wmiPath) 637 wmiPath = (IWbemPath)MTAHelper.CreateInMTA(typeof(WbemDefPath));//new WbemDefPath (); 638 else if (isWbemPathShared) 639 { 640 // Check if this IWbemPath is shared among multiple managed objects. 641 // With this write, it will have to maintain its own copy. 642 wmiPath = CreateWbemPath(this.GetWbemPath()); 643 isWbemPathShared = false; 644 } 645 646 int status = wmiPath.SetServer_(value); 647 648 if (status < 0) 649 { 650 if ((status & 0xfffff000) == 0x80041000) 651 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 652 else 653 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 654 } 655 656 FireIdentifierChanged(); 657 } 658 } 659 } 660 SetNamespacePath(string nsPath, out bool bChange)661 internal string SetNamespacePath(string nsPath, out bool bChange) 662 { 663 int status = (int)ManagementStatus.NoError; 664 string nsOrg = null; 665 string nsNew = null; 666 IWbemPath wmiPathTmp = null; 667 bChange = false; 668 669 Debug.Assert(nsPath != null); 670 671 //Do some validation on the path to make sure it is a valid namespace path (at least syntactically) 672 if (!IsValidNamespaceSyntax(nsPath)) 673 ManagementException.ThrowWithExtendedInfo((ManagementStatus)tag_WBEMSTATUS.WBEM_E_INVALID_NAMESPACE); 674 675 wmiPathTmp = CreateWbemPath(nsPath); 676 if (wmiPath == null) 677 wmiPath = this.CreateWbemPath(""); 678 else if (isWbemPathShared) 679 { 680 // Check if this IWbemPath is shared among multiple managed objects. 681 // With this write, it will have to maintain its own copy. 682 wmiPath = CreateWbemPath(this.GetWbemPath()); 683 isWbemPathShared = false; 684 } 685 686 nsOrg = GetNamespacePath(wmiPath, 687 (int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_NAMESPACE_ONLY); 688 nsNew = GetNamespacePath(wmiPathTmp, 689 (int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_NAMESPACE_ONLY); 690 691 if (String.Compare(nsOrg, nsNew, StringComparison.OrdinalIgnoreCase) != 0) 692 { 693 wmiPath.RemoveAllNamespaces_(); // Out with the old... Ignore status code. 694 695 // Add the new ones in 696 bChange = true; // Now dirty from above. 697 uint nCount = 0; 698 status = wmiPathTmp.GetNamespaceCount_(out nCount); 699 700 if (status >= 0) 701 { 702 for (uint i = 0; i < nCount; i++) 703 { 704 uint uLen = 0; 705 status = wmiPathTmp.GetNamespaceAt_(i, ref uLen, null); 706 707 if (status >= 0) 708 { 709 string nSpace = new String('0', (int) uLen-1); 710 status = wmiPathTmp.GetNamespaceAt_(i, ref uLen, nSpace); 711 if (status >= 0) 712 { 713 status = wmiPath.SetNamespaceAt_(i, nSpace); 714 715 if (status < 0) 716 break; 717 } 718 else 719 break; 720 } 721 else 722 break; 723 } 724 } 725 } 726 else {;} // Continue on. Could have different server name, same ns specified. 727 728 // 729 // Update Server property if specified in the namespace. 730 // eg: "\\MyServer\root\cimv2". 731 // 732 if (status >= 0 && nsPath.Length > 1 && 733 (nsPath[0] == '\\' && nsPath[1] == '\\' || 734 nsPath[0] == '/' && nsPath[1] == '/')) 735 { 736 uint uLen = 0; 737 status = wmiPathTmp.GetServer_(ref uLen, null); 738 739 if (status >= 0 && uLen > 0) 740 { 741 string serverNew = new String ('0', (int) uLen-1); 742 status = wmiPathTmp.GetServer_(ref uLen, serverNew); 743 744 if (status >= 0) 745 { 746 // Compare server name on this object, if specified, to the caller's. 747 // Update this object if different or unspecified. 748 uLen = 0; 749 status = wmiPath.GetServer_(ref uLen, null); // NB: Cannot use property get since it may throw. 750 751 if (status >= 0) 752 { 753 string serverOrg = new String('0', (int)uLen-1); 754 status = wmiPath.GetServer_(ref uLen, serverOrg); 755 756 if (status >= 0 && String.Compare(serverOrg, serverNew, StringComparison.OrdinalIgnoreCase) != 0) 757 status = wmiPath.SetServer_(serverNew); 758 } 759 else if (status == (int)tag_WBEMSTATUS.WBEM_E_NOT_AVAILABLE) 760 { 761 status = wmiPath.SetServer_(serverNew); 762 if (status >= 0) 763 bChange = true; 764 } 765 } 766 } 767 else if (status == (int)tag_WBEMSTATUS.WBEM_E_NOT_AVAILABLE) // No caller-supplied server name; 768 status = (int)ManagementStatus.NoError; // Ignore error. 769 } 770 771 if (status < 0) 772 { 773 if ((status & 0xfffff000) == 0x80041000) 774 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 775 else 776 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 777 } 778 779 return nsNew; 780 } 781 GetNamespacePath(int flags)782 internal string GetNamespacePath(int flags) 783 { 784 return GetNamespacePath(wmiPath, flags); 785 } 786 GetNamespacePath(IWbemPath wbemPath, int flags)787 internal static string GetNamespacePath(IWbemPath wbemPath, int flags) 788 { 789 string pathStr = String.Empty; 790 791 if (null != wbemPath) 792 { 793 // Requesting the namespace path from a parser which has 794 // been only given a relative path results in an incorrect 795 // value being returned (e.g. \\.\). To work 796 // around this, check if there are any namespaces, 797 // and if not just return "". 798 uint nCount = 0; 799 int status = (int)ManagementStatus.NoError; 800 801 status = wbemPath.GetNamespaceCount_(out nCount); 802 803 if (status >= 0 && nCount > 0) 804 { 805 // Get the space we need to reserve 806 uint bufLen = 0; 807 status = wbemPath.GetText_(flags, ref bufLen, null); 808 809 if (status >= 0 && bufLen > 0) 810 { 811 pathStr = new String ('0', (int) bufLen-1); 812 status = wbemPath.GetText_(flags, ref bufLen, pathStr); 813 } 814 } 815 816 if (status < 0) 817 { 818 if (status == (int)tag_WBEMSTATUS.WBEM_E_INVALID_PARAMETER) 819 { 820 // Interpret as unspecified - return "" 821 } 822 else if ((status & 0xfffff000) == 0x80041000) 823 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 824 else 825 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 826 } 827 } 828 829 return pathStr; 830 } 831 832 /// <summary> 833 /// <para>Gets or sets the namespace part of the path. Note that this does not include 834 /// the server name, which can be retrieved separately.</para> 835 /// </summary> 836 /// <value> 837 /// A string containing the namespace 838 /// portion of the path represented in this object. 839 /// </value> 840 [RefreshProperties(RefreshProperties.All)] 841 public string NamespacePath 842 { 843 get 844 { 845 return GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_NAMESPACE_ONLY); 846 } 847 set 848 { 849 bool bChange = false; 850 851 try 852 { 853 // isWbemPathShared handled in internal SetNamespacePath. 854 SetNamespacePath(value, out bChange); 855 } 856 catch (COMException) 857 { 858 throw new ArgumentOutOfRangeException ("value"); 859 } 860 861 if (bChange) 862 FireIdentifierChanged(); 863 } 864 } 865 866 /// <summary> 867 /// Gets or sets the class portion of the path. 868 /// </summary> 869 /// <value> 870 /// A string containing the name of the 871 /// class. 872 /// </value> 873 [RefreshProperties(RefreshProperties.All)] 874 public string ClassName 875 { 876 get 877 { 878 return internalClassName; 879 } 880 set 881 { 882 String oldValue = ClassName; 883 884 // Only set if changed 885 if (0 != String.Compare(oldValue,value,StringComparison.OrdinalIgnoreCase)) 886 { 887 // isWbemPathShared handled in internal className property accessor. 888 internalClassName = value; 889 FireIdentifierChanged(); 890 } 891 } 892 } 893 894 internal string internalClassName 895 { 896 get 897 { 898 String pathStr = String.Empty; 899 int status = (int)ManagementStatus.NoError; 900 901 if (null != wmiPath) 902 { 903 uint bufLen = 0; 904 status = wmiPath.GetClassName_(ref bufLen, null); 905 906 if (status >= 0 && 0 < bufLen) 907 { 908 pathStr = new String ('0', (int) bufLen-1); 909 status = wmiPath.GetClassName_(ref bufLen, pathStr); 910 911 if (status < 0) 912 pathStr = String.Empty; 913 } 914 } 915 916 return pathStr; 917 } 918 set 919 { 920 int status = (int)ManagementStatus.NoError; 921 922 if (wmiPath == null) 923 wmiPath = (IWbemPath)MTAHelper.CreateInMTA(typeof(WbemDefPath));//new WbemDefPath(); 924 else if (isWbemPathShared) 925 { 926 // Check if this IWbemPath is shared among multiple managed objects. 927 // With this write, it will have to maintain its own copy. 928 wmiPath = CreateWbemPath(this.GetWbemPath()); 929 isWbemPathShared = false; 930 } 931 932 try 933 { 934 status = wmiPath.SetClassName_(value); 935 } 936 catch (COMException) 937 { 938 throw new ArgumentOutOfRangeException ("value"); 939 } 940 941 if (status < 0) 942 { 943 if ((status & 0xfffff000) == 0x80041000) 944 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 945 else 946 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 947 } 948 } 949 } 950 951 /// <summary> 952 /// <para>Gets or sets a value indicating whether this is a class path.</para> 953 /// </summary> 954 /// <value> 955 /// <para><see langword='true'/> if this is a class path; otherwise, 956 /// <see langword='false'/>.</para> 957 /// </value> 958 public bool IsClass 959 { 960 get 961 { 962 if (null == wmiPath) 963 return false; 964 965 ulong uInfo = 0; 966 int status = wmiPath.GetInfo_(0, out uInfo); 967 968 if (status < 0) 969 { 970 if ((status & 0xfffff000) == 0x80041000) 971 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 972 else 973 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 974 } 975 976 return (0 != (uInfo & (ulong)tag_WBEM_PATH_STATUS_FLAG.WBEMPATH_INFO_IS_CLASS_REF)); 977 } 978 } 979 980 /// <summary> 981 /// <para>Gets or sets a value indicating whether this is an instance path.</para> 982 /// </summary> 983 /// <value> 984 /// <para><see langword='true'/> if this is an instance path; otherwise, 985 /// <see langword='false'/>.</para> 986 /// </value> 987 public bool IsInstance 988 { 989 get 990 { 991 if (null == wmiPath) 992 return false; 993 994 ulong uInfo = 0; 995 int status = wmiPath.GetInfo_(0, out uInfo); 996 997 if (status < 0) 998 { 999 if ((status & 0xfffff000) == 0x80041000) 1000 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 1001 else 1002 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 1003 } 1004 1005 return (0 != (uInfo & (ulong)tag_WBEM_PATH_STATUS_FLAG.WBEMPATH_INFO_IS_INST_REF)); 1006 } 1007 } 1008 1009 /// <summary> 1010 /// <para>Gets or sets a value indicating whether this is a singleton instance path.</para> 1011 /// </summary> 1012 /// <value> 1013 /// <para><see langword='true'/> if this is a singleton instance path; otherwise, 1014 /// <see langword='false'/>.</para> 1015 /// </value> 1016 public bool IsSingleton 1017 { 1018 get 1019 { 1020 if (null == wmiPath) 1021 return false; 1022 1023 ulong uInfo = 0; 1024 int status = wmiPath.GetInfo_(0, out uInfo); 1025 1026 if (status < 0) 1027 { 1028 if ((status & 0xfffff000) == 0x80041000) 1029 ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 1030 else 1031 Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); 1032 } 1033 1034 return (0 != (uInfo & (ulong)tag_WBEM_PATH_STATUS_FLAG.WBEMPATH_INFO_IS_SINGLETON)); 1035 } 1036 } 1037 } 1038 1039 /// <summary> 1040 /// Converts a String to a ManagementPath 1041 /// </summary> 1042 class ManagementPathConverter : ExpandableObjectConverter 1043 { 1044 1045 /// <summary> 1046 /// Determines if this converter can convert an object in the given source type to the native type of the converter. 1047 /// </summary> 1048 /// <param name='context'>An ITypeDescriptorContext that provides a format context.</param> 1049 /// <param name='sourceType'>A Type that represents the type you wish to convert from.</param> 1050 /// <returns> 1051 /// <para>true if this converter can perform the conversion; otherwise, false.</para> 1052 /// </returns> CanConvertFrom(ITypeDescriptorContext context, Type sourceType)1053 public override Boolean CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 1054 { 1055 if ((sourceType == typeof(ManagementPath))) 1056 { 1057 return true; 1058 } 1059 return base.CanConvertFrom(context,sourceType); 1060 } 1061 1062 /// <summary> 1063 /// Gets a value indicating whether this converter can convert an object to the given destination type using the context. 1064 /// </summary> 1065 /// <param name='context'>An ITypeDescriptorContext that provides a format context.</param> 1066 /// <param name='destinationType'>A Type that represents the type you wish to convert to.</param> 1067 /// <returns> 1068 /// <para>true if this converter can perform the conversion; otherwise, false.</para> 1069 /// </returns> CanConvertTo(ITypeDescriptorContext context, Type destinationType)1070 public override Boolean CanConvertTo(ITypeDescriptorContext context, Type destinationType) 1071 { 1072 if ((destinationType == typeof(InstanceDescriptor))) 1073 { 1074 return true; 1075 } 1076 return base.CanConvertTo(context,destinationType); 1077 } 1078 1079 /// <summary> 1080 /// Converts the given object to another type. The most common types to convert 1081 /// are to and from a string object. The default implementation will make a call 1082 /// to ToString on the object if the object is valid and if the destination 1083 /// type is string. If this cannot convert to the desitnation type, this will 1084 /// throw a NotSupportedException. 1085 /// </summary> 1086 /// <param name='context'>An ITypeDescriptorContext that provides a format context.</param> 1087 /// <param name='culture'>A CultureInfo object. If a null reference (Nothing in Visual Basic) is passed, the current culture is assumed.</param> 1088 /// <param name='value'>The Object to convert.</param> 1089 /// <param name='destinationType'>The Type to convert the value parameter to.</param> 1090 /// <returns>An Object that represents the converted value.</returns> ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)1091 public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) 1092 { 1093 1094 if (destinationType == null) 1095 { 1096 throw new ArgumentNullException("destinationType"); 1097 } 1098 1099 if (value is ManagementPath && destinationType == typeof(InstanceDescriptor)) 1100 { 1101 ManagementPath obj = ((ManagementPath)(value)); 1102 ConstructorInfo ctor = typeof(ManagementPath).GetConstructor(new Type[] {typeof(System.String)}); 1103 if (ctor != null) 1104 { 1105 return new InstanceDescriptor(ctor, new object[] {obj.Path}); 1106 } 1107 } 1108 return base.ConvertTo(context,culture,value,destinationType); 1109 } 1110 } 1111 } 1112