diff --git a/src/Microsoft.Management.Infrastructure/CimClass.cs b/src/Microsoft.Management.Infrastructure/CimClass.cs index e95e45c..2aec828 100644 --- a/src/Microsoft.Management.Infrastructure/CimClass.cs +++ b/src/Microsoft.Management.Infrastructure/CimClass.cs @@ -208,9 +208,7 @@ internal void AssertNotDisposed() public override int GetHashCode() { - // TODO: implement this function? - //return this.ClassHandle.GetClassHashCode(); - return 0; + return this.ClassHandle.GetClassHashCode(); } public override bool Equals(object obj) diff --git a/src/Microsoft.Management.Infrastructure/CimInstance.cs b/src/Microsoft.Management.Infrastructure/CimInstance.cs index 3a3cc4c..650be08 100644 --- a/src/Microsoft.Management.Infrastructure/CimInstance.cs +++ b/src/Microsoft.Management.Infrastructure/CimInstance.cs @@ -346,6 +346,52 @@ private static string PutEscapeCharacterBack(string propValue) } */ + internal static object ConvertFromNativeLayer( + MI_Type type, + MI_Value value, + CimInstance parent = null, + bool clone = false) + { + if (type == MI_Type.MI_INSTANCE) + { + CimInstance instance = new CimInstance( + clone ? value.Instance.Clone() : value.Instance); + if (parent != null) + { + instance.SetCimSessionComputerName(parent.GetCimSessionComputerName()); + instance.SetCimSessionInstanceId(parent.GetCimSessionInstanceId()); + } + return instance; + } + + if (type == MI_Type.MI_INSTANCEA) + { + CimInstance[] arrayOfInstances = new CimInstance[value.InstanceA.Length]; + for (int i = 0; i < value.InstanceA.Length; i++) + { + MI_Instance h = value.InstanceA[i]; + if (h == null) + { + arrayOfInstances[i] = null; + } + else + { + arrayOfInstances[i] = new CimInstance( + clone ? h.Clone() : h); + if (parent != null) + { + arrayOfInstances[i].SetCimSessionComputerName(parent.GetCimSessionComputerName()); + arrayOfInstances[i].SetCimSessionInstanceId(parent.GetCimSessionInstanceId()); + } + } + } + return arrayOfInstances; + } + + return value; + } + + #endregion Helpers #region IDisposable Members diff --git a/src/Microsoft.Management.Infrastructure/CimSession.cs b/src/Microsoft.Management.Infrastructure/CimSession.cs index 197c96b..0da9dc4 100644 --- a/src/Microsoft.Management.Infrastructure/CimSession.cs +++ b/src/Microsoft.Management.Infrastructure/CimSession.cs @@ -369,8 +369,7 @@ protected virtual void Dispose(bool disposing) if (disposing) { - // TODO: Implement and Call ReleaseHandleAsynchronously - //this._handle.Dispose(); + this._handle.Dispose(); } } diff --git a/src/Microsoft.Management.Infrastructure/Internal/ClassHandleExtensionMethods.cs b/src/Microsoft.Management.Infrastructure/Internal/ClassHandleExtensionMethods.cs index f51b6a7..349ee7d 100644 --- a/src/Microsoft.Management.Infrastructure/Internal/ClassHandleExtensionMethods.cs +++ b/src/Microsoft.Management.Infrastructure/Internal/ClassHandleExtensionMethods.cs @@ -15,7 +15,7 @@ public static MI_Class Clone(this MI_Class handleToClone) { return null; } - // TODO: handleToClone.AssertValidInternalState(); + handleToClone.AssertValidInternalState(); MI_Class clonedHandle; MI_Result result = handleToClone.Clone(out clonedHandle); diff --git a/src/Microsoft.Management.Infrastructure/Internal/Data/CimClassQualifierCollection.cs b/src/Microsoft.Management.Infrastructure/Internal/Data/CimClassQualifierCollection.cs index 7a4f643..0ca34b1 100644 --- a/src/Microsoft.Management.Infrastructure/Internal/Data/CimClassQualifierCollection.cs +++ b/src/Microsoft.Management.Infrastructure/Internal/Data/CimClassQualifierCollection.cs @@ -46,8 +46,11 @@ public override CimQualifier this[string qualifierName] MI_QualifierSet qualifierSet; MI_Result result = this.classHandle.GetClassQualifierSet(out qualifierSet); - CimException.ThrowIfMiResultFailure(result); - // TODO: there aren't many comments for the above pattern throughout the MMI sources, but if the above fails we shouldn't throw exception, just return MI_RESULT_NOT_FOUND like below. Make sure all of these cases are accounted for in MMI + + if (result != MI_Result.MI_RESULT_OK) + { + return null; + } MI_Type qualifierType; MI_Flags qualifierFlags; diff --git a/src/Microsoft.Management.Infrastructure/Internal/Data/CimMethodDeclarationOfClass.cs b/src/Microsoft.Management.Infrastructure/Internal/Data/CimMethodDeclarationOfClass.cs index a82b5b3..5da4d41 100644 --- a/src/Microsoft.Management.Infrastructure/Internal/Data/CimMethodDeclarationOfClass.cs +++ b/src/Microsoft.Management.Infrastructure/Internal/Data/CimMethodDeclarationOfClass.cs @@ -29,8 +29,8 @@ public override string Name MI_Result result = this.classHandle.GetMethodAt( (uint)this.index, out name, - out qualifierSet, - out parameterSet); + out qualifierSet, + out parameterSet); CimException.ThrowIfMiResultFailure(result); return name; } @@ -48,8 +48,8 @@ public override CimType ReturnType MI_Result result = this.classHandle.GetMethodAt( (uint)this.index, out name, - out qualifierSet, - out parameterSet); + out qualifierSet, + out parameterSet); CimException.ThrowIfMiResultFailure(result); result = parameterSet.GetMethodReturnType(out type, qualifierSet); CimException.ThrowIfMiResultFailure(result); diff --git a/src/Microsoft.Management.Infrastructure/Internal/Data/CimMethodParameterDeclarationCollection.cs b/src/Microsoft.Management.Infrastructure/Internal/Data/CimMethodParameterDeclarationCollection.cs index a8ce51e..aac555c 100644 --- a/src/Microsoft.Management.Infrastructure/Internal/Data/CimMethodParameterDeclarationCollection.cs +++ b/src/Microsoft.Management.Infrastructure/Internal/Data/CimMethodParameterDeclarationCollection.cs @@ -60,7 +60,10 @@ public override CimMethodParameterDeclaration this[string parameterName] out qualifierSet, out parameterSet); - CimException.ThrowIfMiResultFailure(result); + if (result != MI_Result.MI_RESULT_OK) + { + return null; + } MI_Type parameterType; string referenceClass; diff --git a/src/Microsoft.Management.Infrastructure/Internal/Data/CimMethodParameterQualifierCollection.cs b/src/Microsoft.Management.Infrastructure/Internal/Data/CimMethodParameterQualifierCollection.cs index 84f9108..3c999f6 100644 --- a/src/Microsoft.Management.Infrastructure/Internal/Data/CimMethodParameterQualifierCollection.cs +++ b/src/Microsoft.Management.Infrastructure/Internal/Data/CimMethodParameterQualifierCollection.cs @@ -71,7 +71,11 @@ public override CimQualifier this[string qualifierName] out name, out qualifierSet, out parameterSet); - CimException.ThrowIfMiResultFailure(result); + + if (result != MI_Result.MI_RESULT_OK) + { + return null; + } MI_Type parameterType; string referenceClass; @@ -81,7 +85,11 @@ public override CimQualifier this[string qualifierName] out parameterType, out referenceClass, out methodQualifierSet); - CimException.ThrowIfMiResultFailure(result); + + if (result != MI_Result.MI_RESULT_OK) + { + return null; + } MI_Type qualifierType; MI_Flags qualifierFlags; diff --git a/src/Microsoft.Management.Infrastructure/Internal/Data/CimMethodQualifierCollection.cs b/src/Microsoft.Management.Infrastructure/Internal/Data/CimMethodQualifierCollection.cs index a51e2d9..c0af082 100644 --- a/src/Microsoft.Management.Infrastructure/Internal/Data/CimMethodQualifierCollection.cs +++ b/src/Microsoft.Management.Infrastructure/Internal/Data/CimMethodQualifierCollection.cs @@ -58,7 +58,11 @@ public override CimQualifier this[string methodName] out name, out qualifierSet, out parameterSet); - CimException.ThrowIfMiResultFailure(result); + + if (result != MI_Result.MI_RESULT_OK) + { + return null; + } MI_Type qualifierType; MI_Flags qualifierFlags; diff --git a/src/Microsoft.Management.Infrastructure/Internal/Data/CimPropertyQualifierCollection.cs b/src/Microsoft.Management.Infrastructure/Internal/Data/CimPropertyQualifierCollection.cs index 22c9999..6c7a50a 100644 --- a/src/Microsoft.Management.Infrastructure/Internal/Data/CimPropertyQualifierCollection.cs +++ b/src/Microsoft.Management.Infrastructure/Internal/Data/CimPropertyQualifierCollection.cs @@ -73,7 +73,11 @@ public override CimQualifier this[string qualifierName] out qualifierSet, out flags, out index); - CimException.ThrowIfMiResultFailure(result); + + if (result != MI_Result.MI_RESULT_OK) + { + return null; + } MI_Type qualifierType; MI_Flags qualifierFlags; diff --git a/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncCallbacksReceiverBase.cs b/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncCallbacksReceiverBase.cs index c212acb..965f27f 100644 --- a/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncCallbacksReceiverBase.cs +++ b/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncCallbacksReceiverBase.cs @@ -171,7 +171,7 @@ internal void CallIntoUserCallback( internal abstract void ReportInternalError(CimOperationCallbackProcessingContext callbackProcessingContext, Exception internalError); - private void ReportInternalErrorCore(CimOperationCallbackProcessingContext callbackProcessingContext, Exception internalError) + private void ReportInternalErrorCore(object callbackProcessingContext, Exception internalError) { Debug.Assert(internalError != null, "Caller should make sure internalError != null"); @@ -191,7 +191,7 @@ private void ReportInternalErrorCore(CimOperationCallbackProcessingContext callb internalErrorWhileCancellingOperation); } - this.ReportInternalError(callbackProcessingContext, internalError); + this.ReportInternalError((CimOperationCallbackProcessingContext)callbackProcessingContext, internalError); this._suppressFurtherUserCallbacks = true; } @@ -200,9 +200,8 @@ private void ReportInternalErrorCore(CimOperationCallbackProcessingContext callb public virtual void RegisterAcceptedAsyncCallbacks(MI_OperationCallbacks operationCallbacks, CimOperationOptions operationOptions) { - // TODO: Uncomment and fix two lines below - //operationCallbacks.InternalErrorCallback = this.ReportInternalErrorCore; - //operationCallbacks.ManagedOperationContext = this; + operationCallbacks.InternalErrorCallback = this.ReportInternalErrorCore; + operationCallbacks.ManagedOperationContext = this; } #endregion Dealing with async callbacks diff --git a/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncClassObserverProxy.cs b/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncClassObserverProxy.cs index 1b9d0e5..dd2556a 100644 --- a/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncClassObserverProxy.cs +++ b/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncClassObserverProxy.cs @@ -20,13 +20,14 @@ internal CimAsyncClassObserverProxy(IObserver observer, bool shortenLi } internal void ClassCallback( - CimOperationCallbackProcessingContext callbackProcessingContext, MI_Operation operationHandle, + object callbackProcessingContext, MI_Class ClassHandle, bool moreResults, MI_Result operationResult, String errorMessage, - MI_Instance errorDetailsHandle) + MI_Instance errorDetailsHandle, + MI_OperationCallbacks.MI_OperationCallback_ResultAcknowledgement resultAcknowledgement) { CimClass currentItem = null; if ((ClassHandle != null) && (!ClassHandle.IsNull)) @@ -40,7 +41,7 @@ internal void ClassCallback( try { - this.ProcessNativeCallback(callbackProcessingContext, currentItem, moreResults, operationResult, errorMessage, errorDetailsHandle); + this.ProcessNativeCallback((CimOperationCallbackProcessingContext)callbackProcessingContext, currentItem, moreResults, operationResult, errorMessage, errorDetailsHandle); } finally { @@ -57,8 +58,7 @@ internal void ClassCallback( public override void RegisterAcceptedAsyncCallbacks(MI_OperationCallbacks operationCallbacks, CimOperationOptions operationOptions) { base.RegisterAcceptedAsyncCallbacks(operationCallbacks, operationOptions); - // TODO: Uncomment and fix below - //operationCallbacks.classResult = this.ClassCallback; + operationCallbacks.classResult = this.ClassCallback; } } } \ No newline at end of file diff --git a/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncIndicationObserverProxy.cs b/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncIndicationObserverProxy.cs index 43cc493..49fa049 100644 --- a/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncIndicationObserverProxy.cs +++ b/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncIndicationObserverProxy.cs @@ -20,15 +20,16 @@ internal CimAsyncIndicationObserverProxy(IObserver observ } internal void IndicationResultCallback( - CimOperationCallbackProcessingContext callbackProcessingContext, MI_Operation operationHandle, + object callbackProcessingContext, MI_Instance instanceHandle, String bookMark, String machineID, bool moreResults, MI_Result operationResult, String errorMessage, - MI_Instance errorDetailsHandle) + MI_Instance errorDetailsHandle, + MI_OperationCallbacks.MI_OperationCallback_ResultAcknowledgement resultAcknowledgement) { CimSubscriptionResult currentItem = null; if ((instanceHandle != null) && (!instanceHandle.IsNull)) @@ -42,7 +43,7 @@ internal void IndicationResultCallback( try { - this.ProcessNativeCallback(callbackProcessingContext, currentItem, moreResults, operationResult, errorMessage, errorDetailsHandle); + this.ProcessNativeCallback((CimOperationCallbackProcessingContext)callbackProcessingContext, currentItem, moreResults, operationResult, errorMessage, errorDetailsHandle); } finally { @@ -59,8 +60,7 @@ internal void IndicationResultCallback( public override void RegisterAcceptedAsyncCallbacks(MI_OperationCallbacks operationCallbacks, CimOperationOptions operationOptions) { base.RegisterAcceptedAsyncCallbacks(operationCallbacks, operationOptions); - // TODO: Uncomment and fix below - //operationCallbacks.indicationResult = this.IndicationResultCallback; + operationCallbacks.indicationResult = this.IndicationResultCallback; } } } \ No newline at end of file diff --git a/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncInstanceObserverProxy.cs b/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncInstanceObserverProxy.cs index 1f09d9d..81340ad 100644 --- a/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncInstanceObserverProxy.cs +++ b/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncInstanceObserverProxy.cs @@ -27,13 +27,14 @@ internal CimAsyncInstanceObserverProxy(IObserver observer, } internal void InstanceResultCallback( - CimOperationCallbackProcessingContext callbackProcessingContext, MI_Operation operationHandle, + object callbackProcessingContext, MI_Instance instanceHandle, bool moreResults, MI_Result operationResult, String errorMessage, - MI_Instance errorDetailsHandle) + MI_Instance errorDetailsHandle, + MI_OperationCallbacks.MI_OperationCallback_ResultAcknowledgement resultAcknowledgement) { CimInstance currentItem = null; if ((instanceHandle != null) && (!instanceHandle.IsNull)) @@ -49,7 +50,7 @@ internal void InstanceResultCallback( try { - this.ProcessNativeCallback(callbackProcessingContext, currentItem, moreResults, operationResult, errorMessage, errorDetailsHandle); + this.ProcessNativeCallback((CimOperationCallbackProcessingContext)callbackProcessingContext, currentItem, moreResults, operationResult, errorMessage, errorDetailsHandle); } finally { @@ -66,8 +67,7 @@ internal void InstanceResultCallback( public override void RegisterAcceptedAsyncCallbacks(MI_OperationCallbacks operationCallbacks, CimOperationOptions operationOptions) { base.RegisterAcceptedAsyncCallbacks(operationCallbacks, operationOptions); - // TODO: Uncomment and fix below - //operationCallbacks.instanceResult = this.InstanceResultCallback; + operationCallbacks.instanceResult = this.InstanceResultCallback; } } } \ No newline at end of file diff --git a/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncMethodResultObserverProxy.cs b/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncMethodResultObserverProxy.cs index a3f5248..4a84e90 100644 --- a/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncMethodResultObserverProxy.cs +++ b/src/Microsoft.Management.Infrastructure/Internal/Operations/CimAsyncMethodResultObserverProxy.cs @@ -27,13 +27,14 @@ internal CimAsyncMethodResultObserverProxy(IObserver observ } internal void InstanceResultCallback( - CimOperationCallbackProcessingContext callbackProcessingContext, MI_Operation operationHandle, + object callbackProcessingContext, MI_Instance instanceHandle, bool moreResults, MI_Result operationResult, String errorMessage, - MI_Instance errorDetailsHandle) + MI_Instance errorDetailsHandle, + MI_OperationCallbacks.MI_OperationCallback_ResultAcknowledgement resultAcknowledgement) { CimMethodResult currentItem = null; if ((instanceHandle != null) && (!instanceHandle.IsNull)) @@ -50,7 +51,7 @@ internal void InstanceResultCallback( try { - this.ProcessNativeCallback(callbackProcessingContext, currentItem, moreResults, operationResult, errorMessage, errorDetailsHandle); + this.ProcessNativeCallback((CimOperationCallbackProcessingContext)callbackProcessingContext, currentItem, moreResults, operationResult, errorMessage, errorDetailsHandle); } finally { @@ -63,16 +64,80 @@ internal void InstanceResultCallback( } } } - + + internal void StreamedParameterCallback( + MI_Operation operation, + object callbackProcessingContext, + string parameterName, + MI_Type resultType, + MI_Value result, + MI_OperationCallbacks.MI_OperationCallback_ResultAcknowledgement resultAcknowledgement) + { + object parameterValue = CimInstance.ConvertFromNativeLayer( + resultType, + result, + null, + !this._shortenLifetimeOfResults); + + { + var cimInstance = parameterValue as CimInstance; + if (cimInstance != null) + { + cimInstance.SetCimSessionComputerName(this._CimSessionComputerName); + cimInstance.SetCimSessionInstanceId(this._CimSessionInstanceID); + } + + var cimInstances = parameterValue as CimInstance[]; + if (cimInstances != null) + { + foreach (var i in cimInstances) + { + if (i != null) + { + i.SetCimSessionComputerName(this._CimSessionComputerName); + i.SetCimSessionInstanceId(this._CimSessionInstanceID); + } + } + } + } + + try + { + CimMethodResultBase currentItem = new CimMethodStreamedResult(parameterName, parameterValue, resultType.ToCimType()); + this.ProcessNativeCallback((CimOperationCallbackProcessingContext) callbackProcessingContext, currentItem, true, MI_Result.MI_RESULT_OK, null, null); + } + finally + { + if (this._shortenLifetimeOfResults) + { + var cimInstance = parameterValue as CimInstance; + if (cimInstance != null) + { + cimInstance.Dispose(); + } + + var cimInstances = parameterValue as CimInstance[]; + if (cimInstances != null) + { + foreach (var i in cimInstances) + { + if (i != null) + { + i.Dispose(); + } + } + } + } + } + } + public override void RegisterAcceptedAsyncCallbacks(MI_OperationCallbacks operationCallbacks, CimOperationOptions operationOptions) { base.RegisterAcceptedAsyncCallbacks(operationCallbacks, operationOptions); - // TODO: Uncomment and fix below - //operationCallbacks.instanceResult = this.InstanceResultCallback; + operationCallbacks.instanceResult = this.InstanceResultCallback; if ((operationOptions != null) && (operationOptions.EnableMethodResultStreaming)) { - // TODO: Uncomment and fix below - //operationCallbacks.streamedParameterResult = this.StreamedParameterCallback; + operationCallbacks.streamedParameterResult = this.StreamedParameterCallback; } } } diff --git a/src/Microsoft.Management.Infrastructure/Internal/Operations/CimOperation.cs b/src/Microsoft.Management.Infrastructure/Internal/Operations/CimOperation.cs index 5041dee..a83d262 100644 --- a/src/Microsoft.Management.Infrastructure/Internal/Operations/CimOperation.cs +++ b/src/Microsoft.Management.Infrastructure/Internal/Operations/CimOperation.cs @@ -115,8 +115,7 @@ protected virtual void Dispose(bool disposing) if (disposing) { - // TODO: do we need to call Delete/Dispose here? Looks like it is freed on destruction in MI_Operation - //this._handle.Delete(); + this._handle.Dispose(); if (this._cancellationTokenRegistration != null) { diff --git a/src/Microsoft.Management.Infrastructure/Internal/ValueHelpers.cs b/src/Microsoft.Management.Infrastructure/Internal/ValueHelpers.cs index 026cd1c..12a676d 100644 --- a/src/Microsoft.Management.Infrastructure/Internal/ValueHelpers.cs +++ b/src/Microsoft.Management.Infrastructure/Internal/ValueHelpers.cs @@ -72,18 +72,7 @@ internal static MI_Value ConvertToNativeLayer(object value, CimType cimType) return retval; } - // TODO: What to do with Unknown types? Ignore? Uncomment and remove return line immediately below. - return CimProperty.ConvertToNativeLayer(value, cimType); - /* - if (cimType != CimType.Unknown) - { - return CimProperty.ConvertToNativeLayer(value, cimType); - } - else - { - return value; - } - */ + return (cimType != CimType.Unknown) ? CimProperty.ConvertToNativeLayer(value, cimType) : null; } internal static MI_Value ConvertToNativeLayer(object value) diff --git a/src/Microsoft.Management.Infrastructure/Native/MI_Class.cs b/src/Microsoft.Management.Infrastructure/Native/MI_Class.cs index 8f6e562..00fc10a 100644 --- a/src/Microsoft.Management.Infrastructure/Native/MI_Class.cs +++ b/src/Microsoft.Management.Infrastructure/Native/MI_Class.cs @@ -5,6 +5,31 @@ namespace Microsoft.Management.Infrastructure.Native { internal class MI_Class : MI_NativeObjectWithFT { + internal void AssertValidInternalState() + { + System.Diagnostics.Debug.Assert(this.Ptr != IntPtr.Zero); + } + + + internal int GetClassHashCode() + { + IntPtr classDeclPtr = IntPtr.Zero; + unsafe + { + // Just as easily could be implemented with Marshal + // but that would copy more than the one pointer we need + IntPtr structurePtr = this.Ptr; + if (structurePtr == IntPtr.Zero) + { + throw new InvalidOperationException(); + } + + classDeclPtr = *((IntPtr*)((byte*)structurePtr + MI_ClassMembersClassDeclOffset)); + } + + return classDeclPtr.GetHashCode(); + } + internal MI_Result GetElement( string name, out MI_Value value, @@ -138,6 +163,7 @@ private struct MI_ClassMembers // Marshal implements these with Reflection - pay this hit only once private static int MI_ClassMembersFTOffset = (int)Marshal.OffsetOf("ft"); + private static int MI_ClassMembersClassDeclOffset = (int)Marshal.OffsetOf("classDecl"); private static int MI_ClassMembersSize = Marshal.SizeOf(); private MI_Class(bool isDirect) : base(isDirect) diff --git a/src/Microsoft.Management.Infrastructure/Native/NativeCimCredential.cs b/src/Microsoft.Management.Infrastructure/Native/NativeCimCredential.cs index 2c2a4e0..dbf9825 100644 --- a/src/Microsoft.Management.Infrastructure/Native/NativeCimCredential.cs +++ b/src/Microsoft.Management.Infrastructure/Native/NativeCimCredential.cs @@ -1,5 +1,6 @@ using Microsoft.Management.Infrastructure.Options; using System.Security; +using System; namespace Microsoft.Management.Infrastructure.Native { @@ -7,6 +8,7 @@ public class NativeCimCredential { private SecureString passwordSecureStr; private bool credentialIsCertificate; + internal MI_UserCredentials cred; internal NativeCimCredential(bool bIsCertificate, SecureString secureStr) { @@ -30,38 +32,36 @@ internal void AssertValidInternalState() internal static void CreateCimCredential(string authenticationMechanism, string certificateThumbprint, out NativeCimCredential credential) { - // TODO: Implement - credential = new NativeCimCredential(true, new SecureString()); - } + credential = new NativeCimCredential(true, null); + + credential.cred.usernamePassword.domain = null; + credential.cred.usernamePassword.username = null; + credential.cred.usernamePassword.password = null; - internal static void CreateCimCredential(string authenticationMechanism, string domain, string userName, SecureString password, out NativeCimCredential credential) - { - // TODO: Implement - credential = new NativeCimCredential(true, new SecureString()); + credential.cred.authenticationType = System.Runtime.InteropServices.Marshal.StringToHGlobalUni(authenticationMechanism); + credential.cred.certificateThumbprint = System.Runtime.InteropServices.Marshal.StringToHGlobalUni(certificateThumbprint); } - internal static void CreateCimCredential(string authenticationMechanism, out NativeCimCredential credential) + internal static void CreateCimCredential(string authenticationMechanism, string domain, string userName, SecureString password, out NativeCimCredential credential) { - // TODO: Implement - credential = new NativeCimCredential(true, new SecureString()); - } + credential = new NativeCimCredential(false, password); + credential.cred.certificateThumbprint = IntPtr.Zero; + credential.cred.usernamePassword.password = null; - internal static void CreateCimCredential(CertificateAuthenticationMechanism authenticationMechanism, string certificateThumbprint, out NativeCimCredential credential) - { - // TODO: Implement - credential = new NativeCimCredential(true, new SecureString()); + credential.cred.authenticationType = System.Runtime.InteropServices.Marshal.StringToHGlobalUni(authenticationMechanism); + credential.cred.usernamePassword.domain = domain; + credential.cred.usernamePassword.username = userName; } - internal static void CreateCimCredential(PasswordAuthenticationMechanism authenticationMechanism, string domain, string userName, SecureString password, out NativeCimCredential credential) + internal static void CreateCimCredential(string authenticationMechanism, out NativeCimCredential credential) { - // TODO: Implement - credential = new NativeCimCredential(true, new SecureString()); - } + credential = new NativeCimCredential(false, null); + credential.cred.certificateThumbprint = IntPtr.Zero; + credential.cred.usernamePassword.domain = null; + credential.cred.usernamePassword.username = null; + credential.cred.usernamePassword.password = null; - internal static void CreateCimCredential(ImpersonatedAuthenticationMechanism authenticationMechanism, out NativeCimCredential credential) - { - // TODO: Implement - credential = new NativeCimCredential(true, new SecureString()); + credential.cred.authenticationType = System.Runtime.InteropServices.Marshal.StringToHGlobalUni(authenticationMechanism); } } } \ No newline at end of file diff --git a/src/Microsoft.Management.Infrastructure/Native/Structures/MI_OperationCallbacks.cs b/src/Microsoft.Management.Infrastructure/Native/Structures/MI_OperationCallbacks.cs index 6ee9e08..9129828 100644 --- a/src/Microsoft.Management.Infrastructure/Native/Structures/MI_OperationCallbacks.cs +++ b/src/Microsoft.Management.Infrastructure/Native/Structures/MI_OperationCallbacks.cs @@ -33,6 +33,12 @@ internal class MI_OperationCallbacksNative internal MI_OperationCallback_StreamedParameter streamedParameterResult; + internal InternalErrorCallbackDelegate InternalErrorCallback; + + internal System.Object ManagedOperationContext; + + internal delegate void InternalErrorCallbackDelegate(object callbackContextWhereInternalErrorOccurred, System.Exception exception); + internal delegate void MI_OperationCallback_PromptUserResult(MI_Operation operation, MI_OperationCallback_ResponseType responseType); internal delegate void MI_OperationCallback_ResultAcknowledgement(MI_Operation operation); diff --git a/src/Microsoft.Management.Infrastructure/Options/CimCredential.cs b/src/Microsoft.Management.Infrastructure/Options/CimCredential.cs index 326cf2b..d0a3104 100644 --- a/src/Microsoft.Management.Infrastructure/Options/CimCredential.cs +++ b/src/Microsoft.Management.Infrastructure/Options/CimCredential.cs @@ -154,7 +154,6 @@ public CimCredential(ImpersonatedAuthenticationMechanism authenticationMechanism NativeCimCredential.CreateCimCredential(strAuthenticationMechanism, out credential); } - // TODO: return proper credential type here - //internal NativeCimCredentialHandle GetCredential(){ return credential; } + internal NativeCimCredential GetCredential(){ return credential; } } } \ No newline at end of file diff --git a/src/Microsoft.Management.Infrastructure/Options/CimSessionOptions.cs b/src/Microsoft.Management.Infrastructure/Options/CimSessionOptions.cs index b2a95a0..fcd7b77 100644 --- a/src/Microsoft.Management.Infrastructure/Options/CimSessionOptions.cs +++ b/src/Microsoft.Management.Infrastructure/Options/CimSessionOptions.cs @@ -8,6 +8,8 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Globalization; +using System.Security; +using System.Runtime.InteropServices; namespace Microsoft.Management.Infrastructure.Options { @@ -173,6 +175,29 @@ public void SetCustomOption(string optionName, UInt32 optionValue) CimException.ThrowIfMiResultFailure(result); } + public static string ConvertToUnsecureString(SecureString securePassword) + { + if (securePassword == null) + { + throw new ArgumentNullException("securePassword"); + } + + IntPtr unmanagedString = IntPtr.Zero; + try + { +#if (!_CORECLR) + unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword); +#else + unmanagedString = SecureStringMarshal.SecureStringToCoTaskMemUnicode(securePassword); +#endif + return Marshal.PtrToStringUni(unmanagedString); + } + finally + { + Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString); + } + } + /// /// Sets a Destination Credential /// @@ -180,45 +205,27 @@ public void SetCustomOption(string optionName, UInt32 optionValue) /// Thrown when is null public void AddDestinationCredentials(CimCredential credential) { - // TODO: Once credentials are working, uncomment and fix - /* - if (credential == null) - { - throw new ArgumentNullException("credential"); - } - this.AssertNotDisposed(); + if (credential == null) + { + throw new ArgumentNullException("credential"); + } + this.AssertNotDisposed(); - MI_UserCredentials nativeCredential; - SecureString securePassword = credential.GetSecureString(); - IntPtr passwordPtr = IntPtr.Zero; + MI_Result result = MI_Result.MI_RESULT_OK; + + //Additional processing for securePasswords + SecureString securePassword = credential.GetCredential().GetSecureString();; if( securePassword != null && securePassword.Length > 0) { - #if(!_CORECLR) - passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(securePassword); - #else - passwordPtr = SecureStringMarshal.SecureStringToCoTaskMemUnicode(securePassword); - #endif - nativeCredential.usernamePassword.password = passwordPtr; + credential.GetCredential().cred.usernamePassword.password = ConvertToUnsecureString(securePassword); } else { - nativeCredential.usernamePassword.password = null; + credential.GetCredential().cred.usernamePassword.password = null; } - MI_Result result = this.DestinationOptionsHandleOnDemand.AddCredentials("__MI_DESTINATIONOPTIONS_DESTINATION_CREDENTIALS", - nativeCredential, - MI_DestinationOptionFlags.Unused); - - if ( passwordPtr != IntPtr.Zero ) - { - #if(!_CORECLR) - Marshal.FreeHGlobal(passwordPtr); - #else - SecureStringMarshal.ZeroFreeCoTaskMemUnicode(passwordPtr); - #endif - } - CimException.ThrowIfMiResultFailure(result); - */ + result = this.DestinationOptionsHandle.AddCredentials("__MI_DESTINATIONOPTIONS_DESTINATION_CREDENTIALS", credential.GetCredential().cred, 0); + CimException.ThrowIfMiResultFailure(result); } /// @@ -388,4 +395,5 @@ object ICloneable.Clone() #endregion ICloneable Members } -} \ No newline at end of file +} + \ No newline at end of file diff --git a/src/Microsoft.Management.Infrastructure/Options/Internal/CimOperationOptions.cs b/src/Microsoft.Management.Infrastructure/Options/Internal/CimOperationOptions.cs index 2864e3c..4147533 100644 --- a/src/Microsoft.Management.Infrastructure/Options/Internal/CimOperationOptions.cs +++ b/src/Microsoft.Management.Infrastructure/Options/Internal/CimOperationOptions.cs @@ -311,25 +311,25 @@ public void SetOption(string optionName, UInt32 optionValue) #region PSSEMANTICS internal void WriteMessageCallbackInternal( - CimOperationCallbackProcessingContext callbackProcessingContext, MI_Operation operationHandle, - UInt32 channel, + object callbackProcessingContext, + MI_WriteMessageChannel channel, string message) { if (_writeMessageCallback != null) { - var callbacksReceiverBase = (CimAsyncCallbacksReceiverBase)callbackProcessingContext.ManagedOperationContext; + var callbacksReceiverBase = (CimAsyncCallbacksReceiverBase)((CimOperationCallbackProcessingContext)callbackProcessingContext).ManagedOperationContext; callbacksReceiverBase.CallIntoUserCallback( - callbackProcessingContext, - () => _writeMessageCallback(channel, message)); + (CimOperationCallbackProcessingContext)callbackProcessingContext, + () => _writeMessageCallback((uint)channel, message)); } } private WriteMessageCallback _writeMessageCallback; private void WriteProgressCallbackInternal( - CimOperationCallbackProcessingContext callbackProcessingContext, MI_Operation operationHandle, + object callbackProcessingContext, string activity, string currentOperation, string statusDescription, @@ -338,9 +338,9 @@ private void WriteProgressCallbackInternal( { if (_writeProgressCallback != null) { - var callbacksReceiverBase = (CimAsyncCallbacksReceiverBase)callbackProcessingContext.ManagedOperationContext; + var callbacksReceiverBase = (CimAsyncCallbacksReceiverBase)((CimOperationCallbackProcessingContext)callbackProcessingContext).ManagedOperationContext; callbacksReceiverBase.CallIntoUserCallback( - callbackProcessingContext, + (CimOperationCallbackProcessingContext)callbackProcessingContext, () => _writeProgressCallback(activity, currentOperation, statusDescription, percentageCompleted, secondsRemaining)); } } @@ -348,12 +348,11 @@ private void WriteProgressCallbackInternal( private WriteProgressCallback _writeProgressCallback; internal void WriteErrorCallbackInternal( - CimOperationCallbackProcessingContext callbackProcessingContext, MI_Operation operationHandle, + object callbackProcessingContext, MI_Instance instanceHandle, - out MI_OperationCallback_ResponseType response) + MI_OperationCallbacks.MI_OperationCallback_PromptUserResult promptUserResult) { - response = MI_OperationCallback_ResponseType.Yes; if (_writeErrorCallback != null) { Debug.Assert(instanceHandle != null, "Caller should verify instance != null"); @@ -363,16 +362,18 @@ internal void WriteErrorCallbackInternal( if (!instanceHandle.IsNull) { cimInstance = new CimInstance(instanceHandle.Clone()); - var callbacksReceiverBase = (CimAsyncCallbacksReceiverBase)callbackProcessingContext.ManagedOperationContext; + var callbacksReceiverBase = (CimAsyncCallbacksReceiverBase)((CimOperationCallbackProcessingContext)callbackProcessingContext).ManagedOperationContext; CimResponseType userResponse = CimResponseType.None; callbacksReceiverBase.CallIntoUserCallback( - callbackProcessingContext, + (CimOperationCallbackProcessingContext)callbackProcessingContext, delegate { userResponse = _writeErrorCallback(cimInstance); }); - response = (MI_OperationCallback_ResponseType)userResponse; + promptUserResult(operationHandle, (MI_OperationCallback_ResponseType)userResponse); + return; } } finally { + promptUserResult(operationHandle, MI_OperationCallback_ResponseType.Yes); if (cimInstance != null) { cimInstance.Dispose(); @@ -384,22 +385,24 @@ internal void WriteErrorCallbackInternal( private WriteErrorCallback _writeErrorCallback; internal void PromptUserCallbackInternal( - CimOperationCallbackProcessingContext callbackProcessingContext, MI_Operation operationHandle, + object callbackProcessingContext, string message, MI_PromptType promptType, - out MI_OperationCallback_ResponseType response) + MI_OperationCallbacks.MI_OperationCallback_PromptUserResult promptUserResult) { - response = MI_OperationCallback_ResponseType.Yes; if (_promptUserCallback != null) { - var callbacksReceiverBase = (CimAsyncCallbacksReceiverBase)callbackProcessingContext.ManagedOperationContext; + var callbacksReceiverBase = (CimAsyncCallbacksReceiverBase)((CimOperationCallbackProcessingContext)callbackProcessingContext).ManagedOperationContext; CimResponseType userResponse = CimResponseType.None; callbacksReceiverBase.CallIntoUserCallback( - callbackProcessingContext, + (CimOperationCallbackProcessingContext)callbackProcessingContext, delegate { userResponse = _promptUserCallback(message, (CimPromptType)promptType); }); - response = (MI_OperationCallback_ResponseType)userResponse; + promptUserResult(operationHandle, (MI_OperationCallback_ResponseType)userResponse); + return; } + + promptUserResult(operationHandle, MI_OperationCallback_ResponseType.Yes); } private PromptUserCallback _promptUserCallback; @@ -479,8 +482,8 @@ public WriteMessageCallback WriteMessage } this.AssertNotDisposed(); _writeMessageCallback = value; - // TODO: Get callbacks working - //OperationCallback.writeMessage = this.WriteMessageCallbackInternal; + + OperationCallback.writeMessage = this.WriteMessageCallbackInternal; } } @@ -499,8 +502,7 @@ public WriteProgressCallback WriteProgress } this.AssertNotDisposed(); _writeProgressCallback = value; - // TODO: Get callbacks working - //OperationCallback.WriteProgressCallback = this.WriteProgressCallbackInternal; + OperationCallback.writeProgress = this.WriteProgressCallbackInternal; } } @@ -519,8 +521,7 @@ public WriteErrorCallback WriteError } this.AssertNotDisposed(); _writeErrorCallback = value; - // TODO: Get callbacks working - //OperationCallback.WriteErrorCallback = this.WriteErrorCallbackInternal; + OperationCallback.writeError = this.WriteErrorCallbackInternal; } } @@ -539,8 +540,7 @@ public PromptUserCallback PromptUser } this.AssertNotDisposed(); _promptUserCallback = value; - // TODO: Get callbacks working - //OperationCallback.PromptUserCallback = this.PromptUserCallbackInternal; + OperationCallback.promptUser = this.PromptUserCallbackInternal; } } @@ -730,9 +730,9 @@ public void SetCustomOption(string optionName, object optionValue, CimType cimTy MI_Result result = this.OperationOptionsHandleOnDemand.SetCustomOption( optionName, cimType.FromCimType(), - nativeLayerValue, + nativeLayerValue, mustComply, - flags); + flags); CimException.ThrowIfMiResultFailure(result); } @@ -860,11 +860,10 @@ static internal MI_OperationCallbacks GetOperationCallbacks(this CimOperationOpt var operationCallbacks = new MI_OperationCallbacks(); if (operationOptions != null) { - // TODO: Uncomment these - //operationCallbacks.writeError = operationOptions.OperationCallback.WriteErrorCallback; - //operationCallbacks.writeMessage = operationOptions.OperationCallback.WriteMessageCallback; - //operationCallbacks.writeProgress = operationOptions.OperationCallback.WriteProgressCallback; - //operationCallbacks.promptUser = operationOptions.OperationCallback.PromptUserCallback; + operationCallbacks.writeError = operationOptions.OperationCallback.writeError; + operationCallbacks.writeMessage = operationOptions.OperationCallback.writeMessage; + operationCallbacks.writeProgress = operationOptions.OperationCallback.writeProgress; + operationCallbacks.promptUser = operationOptions.OperationCallback.promptUser; } return operationCallbacks; } diff --git a/src/Microsoft.Management.Infrastructure/Options/Internal/CimSubscriptionDeliveryOptions.cs b/src/Microsoft.Management.Infrastructure/Options/Internal/CimSubscriptionDeliveryOptions.cs index 84ed9e9..f98e3ec 100644 --- a/src/Microsoft.Management.Infrastructure/Options/Internal/CimSubscriptionDeliveryOptions.cs +++ b/src/Microsoft.Management.Infrastructure/Options/Internal/CimSubscriptionDeliveryOptions.cs @@ -171,10 +171,8 @@ public void SetInterval(string optionName, TimeSpan optionValue, UInt32 flags) } this.AssertNotDisposed(); - // TODO: convert optionValue to MI_Interval - MI_Interval interval; - interval.days = interval.hours = interval.minutes = interval.seconds = interval.microseconds = interval.__padding1 = interval.__padding2 = interval.__padding3 = 0; - MI_Result result = this._subscriptionDeliveryOptionsHandle.SetInterval(optionName, interval, flags); + MI_Datetime dt = new MI_Datetime(optionValue); + MI_Result result = this._subscriptionDeliveryOptionsHandle.SetInterval(optionName, dt.interval, flags); CimException.ThrowIfMiResultFailure(result); } @@ -197,9 +195,8 @@ public void AddCredentials(string optionName, CimCredential optionValue, UInt32 } this.AssertNotDisposed(); - // TODO: Implement this - //MI_Result result = this._subscriptionDeliveryOptionsHandle.SubscriptionDeliveryOptionsMethods.AddCredentials(optionName, optionValue.GetCredential(), flags); - //CimException.ThrowIfMiResultFailure(result); + MI_Result result = this._subscriptionDeliveryOptionsHandle.AddCredentials(optionName, optionValue.GetCredential().cred, flags); + CimException.ThrowIfMiResultFailure(result); } #endregion Options diff --git a/src/Microsoft.Management.Infrastructure/Options/WSManSessionOptions.cs b/src/Microsoft.Management.Infrastructure/Options/WSManSessionOptions.cs index 0e1d1e2..730d149 100644 --- a/src/Microsoft.Management.Infrastructure/Options/WSManSessionOptions.cs +++ b/src/Microsoft.Management.Infrastructure/Options/WSManSessionOptions.cs @@ -7,6 +7,7 @@ using Microsoft.Management.Infrastructure.Options.Internal; using System; using System.Globalization; +using System.Security; namespace Microsoft.Management.Infrastructure.Options { @@ -445,9 +446,21 @@ public void AddProxyCredentials(CimCredential credential) } this.AssertNotDisposed(); - // TODO: Not trivial to port AddProxyCredentials - //MI_Result result = this.DestinationOptionsHandleOnDemand.AddProxyCredentials(credential.GetCredential()); - //CimException.ThrowIfMiResultFailure(result); + MI_Result result = MI_Result.MI_RESULT_OK; + + //Additional processing for securePasswords + SecureString securePassword = credential.GetCredential().GetSecureString(); ; + if (securePassword != null && securePassword.Length > 0) + { + credential.GetCredential().cred.usernamePassword.password = ConvertToUnsecureString(securePassword); + } + else + { + credential.GetCredential().cred.usernamePassword.password = null; + } + + result = this.DestinationOptionsHandle.AddCredentials("__MI_DESTINATIONOPTIONS_PROXY_CREDENTIALS", credential.GetCredential().cred, 0); + CimException.ThrowIfMiResultFailure(result); } } } \ No newline at end of file diff --git a/src/Microsoft.Management.Infrastructure/Serialization/CimDeserializer.cs b/src/Microsoft.Management.Infrastructure/Serialization/CimDeserializer.cs index 6de4bbb..48b4ad1 100644 --- a/src/Microsoft.Management.Infrastructure/Serialization/CimDeserializer.cs +++ b/src/Microsoft.Management.Infrastructure/Serialization/CimDeserializer.cs @@ -28,8 +28,7 @@ private CimDeserializer(string format, uint flags) Debug.Assert(!string.IsNullOrEmpty(format), "Caller should verify that format != null"); MI_Deserializer tmpHandle; - // TODO: Fix MI_SerializerFlags in next line to come from "flags" - MI_Result result = CimApplication.Handle.NewDeserializer(MI_SerializerFlags.None, format, out tmpHandle); + MI_Result result = CimApplication.Handle.NewDeserializer((MI_SerializerFlags)flags, format, out tmpHandle); if (result == MI_Result.MI_RESULT_INVALID_PARAMETER) { throw new ArgumentOutOfRangeException("format"); diff --git a/src/Microsoft.Management.Infrastructure/Serialization/CimMofDeserializer.cs b/src/Microsoft.Management.Infrastructure/Serialization/CimMofDeserializer.cs index 4182e7b..0a4e9a6 100644 --- a/src/Microsoft.Management.Infrastructure/Serialization/CimMofDeserializer.cs +++ b/src/Microsoft.Management.Infrastructure/Serialization/CimMofDeserializer.cs @@ -443,8 +443,7 @@ private void Dispose(bool disposing) if (disposing) { - // TODO: When MI API supports Delete/Dispose, uncomment - //this._myHandle.Dispose(); + this._myHandle.Dispose(); } _disposed = true; diff --git a/src/Microsoft.Management.Infrastructure/Serialization/CimMofSerializer.cs b/src/Microsoft.Management.Infrastructure/Serialization/CimMofSerializer.cs index 23f5606..5296510 100644 --- a/src/Microsoft.Management.Infrastructure/Serialization/CimMofSerializer.cs +++ b/src/Microsoft.Management.Infrastructure/Serialization/CimMofSerializer.cs @@ -22,8 +22,7 @@ private static CimSerializer CreateCimMofSerializer(string format, uint flags) Debug.Assert(!string.IsNullOrEmpty(format), "Caller should verify that format != null"); MI_Serializer tmpHandle; - // TODO: Fix MI_SerializerFlags in next line to come from "flags" - MI_Result result = CimApplication.Handle.NewSerializer(MI_SerializerFlags.None, + MI_Result result = CimApplication.Handle.NewSerializer((MI_SerializerFlags)flags, format, out tmpHandle); if (result == MI_Result.MI_RESULT_INVALID_PARAMETER) diff --git a/src/Microsoft.Management.Infrastructure/Serialization/CimSerializer.cs b/src/Microsoft.Management.Infrastructure/Serialization/CimSerializer.cs index 5948691..f7974da 100644 --- a/src/Microsoft.Management.Infrastructure/Serialization/CimSerializer.cs +++ b/src/Microsoft.Management.Infrastructure/Serialization/CimSerializer.cs @@ -342,8 +342,7 @@ private void Dispose(bool disposing) if (disposing) { - // TODO: Uncomment once this function is implemented - //this._myHandle.Delete(); + this._myHandle.Dispose(); } _disposed = true; diff --git a/test/Microsoft.Management.Infrastructure.Tests/NativeTests/SessionTests.cs b/test/Microsoft.Management.Infrastructure.Tests/NativeTests/SessionTests.cs index d74ae83..b9ef1ea 100644 --- a/test/Microsoft.Management.Infrastructure.Tests/NativeTests/SessionTests.cs +++ b/test/Microsoft.Management.Infrastructure.Tests/NativeTests/SessionTests.cs @@ -200,5 +200,41 @@ public void SimpleGetClass() Assert.Equal(TestGetClassParameterType, parameterType, "Expect parameter type to be the documented type"); Assert.Equal(TestGetClassParameterIndex, parameterIndex, "Expect the power state to be the first parameter"); } + + [WindowsFact] + public void ClassHashCode_Sanity() + { + MI_Operation cimClassOperation1; + MMI.Tests.Native.StaticFixtures.Session.GetClass(MI_OperationFlags.Default, null, TestGetClassNamespace, TestGetClassClassName, null, out cimClassOperation1); + MI_Class cimClass1; + bool moreResults1; + MI_Result operationRes1; + MI_Instance completionDetails1; + string errorMessage1; + var res1 = cimClassOperation1.GetClass(out cimClass1, out moreResults1, out operationRes1, out errorMessage1, out completionDetails1); + MIAssert.Succeeded(res1); + MIAssert.Succeeded(operationRes1); + Assert.False(moreResults1, "Expect no more results after getting named class"); + + MI_Operation cimClassOperation2; + MMI.Tests.Native.StaticFixtures.Session.GetClass(MI_OperationFlags.Default, null, TestGetClassNamespace, TestGetClassClassName, null, out cimClassOperation2); + MI_Class cimClass2; + bool moreResults2; + MI_Result operationRes2; + MI_Instance completionDetails2; + string errorMessage2; + var res2 = cimClassOperation2.GetClass(out cimClass2, out moreResults2, out operationRes2, out errorMessage2, out completionDetails2); + MIAssert.Succeeded(res2); + MIAssert.Succeeded(operationRes2); + Assert.False(moreResults2, "Expect no more results after getting named class"); + + int hash1 = cimClass1.GetClassHashCode(); + int hash2 = cimClass2.GetClassHashCode(); + + Assert.Equal(hash1, hash2, "MI_Class HashCodes are not identical for two objects of the same class."); + + cimClassOperation1.Close(); + cimClassOperation2.Close(); + } } }