File: Instrumentation\SchemaRegistration.cs
Project: ndp\fx\src\wmi\managed\System\Management\System.Management.csproj (System.Management)
//------------------------------------------------------------------------------
// <copyright from='1997' to='2001' company='Microsoft Corporation'>           
//    Copyright (c) Microsoft Corporation. All Rights Reserved.                
//    Information Contained Herein is Proprietary and Confidential.            
// </copyright>                                                                
//------------------------------------------------------------------------------
 
// 
namespace System.Management.Instrumentation
{
    using System;
    using System.Reflection;
    using System.Collections;
    using System.Collections.Specialized;
    using System.Configuration.Install;
    using System.Management;
    using Microsoft.Win32;
    using System.IO;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Globalization;
    using System.Runtime.Versioning;
	
    class SchemaNaming
    {
 
        class InstallLogWrapper
        {
            InstallContext context = null;
            public InstallLogWrapper(InstallContext context)
            {
                this.context = context;
            }
            public void LogMessage(string str)
            {
                if(null != context)
                    context.LogMessage(str);
            }
        }
 
        public static SchemaNaming GetSchemaNaming(Assembly assembly)
        {
            InstrumentedAttribute attr = InstrumentedAttribute.GetAttribute(assembly);
 
            // See if this assembly provides instrumentation
            if(null == attr)
                return null;
 
            return new SchemaNaming(attr.NamespaceName, attr.SecurityDescriptor, assembly);
        }
 
        Assembly assembly;
        SchemaNaming(string namespaceName, string securityDescriptor, Assembly assembly)
        {
            this.assembly = assembly;
            assemblyInfo = new AssemblySpecificNaming(namespaceName, securityDescriptor, assembly);
 
			if ( DoesInstanceExist(RegistrationPath) == false )
			{
				assemblyInfo.DecoupledProviderInstanceName = AssemblyNameUtility.UniqueToAssemblyMinorVersion(assembly);
			}
        }
 
        ///////////////////////////////////////////
        // string constants
        const string Win32ProviderClassName = "__Win32Provider";
        const string EventProviderRegistrationClassName = "__EventProviderRegistration";
        const string InstanceProviderRegistrationClassName = "__InstanceProviderRegistration";
        const string DecoupledProviderClassName = "MSFT_DecoupledProvider";
        const string ProviderClassName = "WMINET_ManagedAssemblyProvider";
        const string InstrumentationClassName = "WMINET_Instrumentation";
        const string InstrumentedAssembliesClassName = "WMINET_InstrumentedAssembly";
        const string DecoupledProviderCLSID = "{54D8502C-527D-43f7-A506-A9DA075E229C}";
        const string GlobalWmiNetNamespace = @"root\MicrosoftWmiNet";
        const string InstrumentedNamespacesClassName = "WMINET_InstrumentedNamespaces";
        const string NamingClassName = "WMINET_Naming";
 
 
        ///////////////////////////////////////////
        // class that holds read only naming info
        // specific to an assembly
        private class AssemblySpecificNaming
        {
           [ResourceExposure(ResourceScope.None),ResourceConsumption(ResourceScope.Machine,ResourceScope.Machine)]
           public AssemblySpecificNaming(string namespaceName, string securityDescriptor, Assembly assembly)
            {
                this.namespaceName = namespaceName;
                this.securityDescriptor = securityDescriptor;
                this.decoupledProviderInstanceName = AssemblyNameUtility.UniqueToAssemblyFullVersion(assembly);
                this.assemblyUniqueIdentifier = AssemblyNameUtility.UniqueToAssemblyBuild(assembly);
                this.assemblyName = assembly.FullName;
                this.assemblyPath = assembly.Location;
            }
 
            string namespaceName;
            string securityDescriptor;
            string decoupledProviderInstanceName;
            string assemblyUniqueIdentifier;
            string assemblyName;
            string assemblyPath;
 
            public string NamespaceName {get {return namespaceName;} }
            public string SecurityDescriptor {get {return securityDescriptor;} }
            public string DecoupledProviderInstanceName {get {return decoupledProviderInstanceName;}  set { decoupledProviderInstanceName=value;}}
            public string AssemblyUniqueIdentifier {get {return assemblyUniqueIdentifier;} }
            public string AssemblyName {get {return assemblyName;} }
            public string AssemblyPath {get {return assemblyPath;} }
        }
 
        ///////////////////////////////////////////
        // Accessors for name information
        // After these methods, there should be no
        // use of the lower case names
        AssemblySpecificNaming assemblyInfo;
 
        public string NamespaceName {get {return assemblyInfo.NamespaceName;} }
        public string SecurityDescriptor {get {return assemblyInfo.SecurityDescriptor;} }
		public string DecoupledProviderInstanceName {get {return assemblyInfo.DecoupledProviderInstanceName;} set {assemblyInfo.DecoupledProviderInstanceName=value;}}
        string AssemblyUniqueIdentifier {get {return assemblyInfo.AssemblyUniqueIdentifier;} }
        string AssemblyName {get {return assemblyInfo.AssemblyName;} }
        string AssemblyPath {get {return assemblyInfo.AssemblyPath;} }
 
        string Win32ProviderClassPath {get {return MakeClassPath(assemblyInfo.NamespaceName, Win32ProviderClassName);} }
        string DecoupledProviderClassPath {get {return MakeClassPath(assemblyInfo.NamespaceName, DecoupledProviderClassName);} }
        string InstrumentationClassPath {get {return MakeClassPath(assemblyInfo.NamespaceName, InstrumentationClassName);} }
        string EventProviderRegistrationClassPath {get {return MakeClassPath(assemblyInfo.NamespaceName, EventProviderRegistrationClassName);} }
        string EventProviderRegistrationPath {get {return AppendProperty(EventProviderRegistrationClassPath, "provider", @"\\\\.\\"+ProviderPath.Replace(@"\", @"\\").Replace(@"""", @"\"""));} }
        string InstanceProviderRegistrationClassPath {get {return MakeClassPath(assemblyInfo.NamespaceName, InstanceProviderRegistrationClassName);} }
        string InstanceProviderRegistrationPath {get {return AppendProperty(InstanceProviderRegistrationClassPath, "provider", @"\\\\.\\"+ProviderPath.Replace(@"\", @"\\").Replace(@"""", @"\"""));} }
 
        string ProviderClassPath {get {return MakeClassPath(assemblyInfo.NamespaceName, ProviderClassName);} }
        string ProviderPath {get {return AppendProperty(ProviderClassPath, "Name", assemblyInfo.DecoupledProviderInstanceName);} }
        string RegistrationClassPath {get {return MakeClassPath(assemblyInfo.NamespaceName, InstrumentedAssembliesClassName);} }
        string RegistrationPath {get {return AppendProperty(RegistrationClassPath, "Name", assemblyInfo.DecoupledProviderInstanceName);} }
        string GlobalRegistrationNamespace {get {return GlobalWmiNetNamespace;} }
        string GlobalInstrumentationClassPath {get {return MakeClassPath(GlobalWmiNetNamespace, InstrumentationClassName);} }
        string GlobalRegistrationClassPath {get {return MakeClassPath(GlobalWmiNetNamespace, InstrumentedNamespacesClassName);} }
        string GlobalRegistrationPath {get {return AppendProperty(GlobalRegistrationClassPath, "NamespaceName", assemblyInfo.NamespaceName.Replace(@"\", @"\\"));} }
        string GlobalNamingClassPath {get {return MakeClassPath(GlobalWmiNetNamespace, NamingClassName);} }
 
        string DataDirectory {get {return Path.Combine(WMICapabilities.FrameworkDirectory, NamespaceName);} }
        string MofPath {get {return Path.Combine(DataDirectory, DecoupledProviderInstanceName + ".mof");} }
        string CodePath {get {return Path.Combine(DataDirectory, DecoupledProviderInstanceName + ".cs");} }
        string PrecompiledAssemblyPath {get {return Path.Combine(DataDirectory, DecoupledProviderInstanceName + ".dll");} }
 
        static string MakeClassPath(string namespaceName, string className)
        {
            return namespaceName + ":" + className;
        }
 
        static string AppendProperty(string classPath, string propertyName, string propertyValue)
        {
            return classPath+'.'+propertyName+"=\""+propertyValue+'\"';
        }
 
        public bool IsAssemblyRegistered()
        {
            if(DoesInstanceExist(RegistrationPath) )
            {
                ManagementObject inst = new ManagementObject(RegistrationPath);
//                return (0==AssemblyUniqueIdentifier.ToLower(CultureInfo.InvariantCulture).CompareTo(inst["RegisteredBuild"].ToString().ToLower()));
                return (0==String.Compare(AssemblyUniqueIdentifier,inst["RegisteredBuild"].ToString(),StringComparison.OrdinalIgnoreCase));
            }
            return false;
        }
 
		// Schema has to be compared only if both the below conditions are met
		// 1. Intance of WMI_InstrumentedAssembly is already present for the given name
		// 2. If the registeredBuild - which includes unique value for the provider assembly is different
		private bool IsSchemaToBeCompared()
		{
			bool bRet = false;
 
			if (DoesInstanceExist(RegistrationPath))
			{
				ManagementObject obj = new ManagementObject(RegistrationPath);
 
				//                return (0==AssemblyUniqueIdentifier.ToLower(CultureInfo.InvariantCulture).CompareTo(inst["RegisteredBuild"].ToString().ToLower()));
				bRet = (0 != String.Compare(AssemblyUniqueIdentifier, obj["RegisteredBuild"].ToString(), StringComparison.OrdinalIgnoreCase));
			}
 
			return bRet;
		}
        ManagementObject registrationInstance = null;
        ManagementObject RegistrationInstance
        {
            get
            {
                if(null == registrationInstance)
                    registrationInstance = new ManagementObject(RegistrationPath);
                return registrationInstance;
            }
        }
 
        public string Code
        {
            [ResourceExposure(ResourceScope.None),ResourceConsumption(ResourceScope.Machine,ResourceScope.Machine)]
            get
            {
                using(StreamReader reader = new StreamReader(CodePath))
                {
                	return reader.ReadToEnd();
                }
            	}
        }
 
		public string Mof
		{
                    [ResourceExposure(ResourceScope.None),ResourceConsumption(ResourceScope.Machine,ResourceScope.Machine)]
			get
			{
				using(StreamReader reader = new StreamReader(MofPath))
				{
					return reader.ReadToEnd();
				}
			}
		}
 
        public Assembly PrecompiledAssembly
        {
            [ResourceExposure(ResourceScope.Machine),ResourceConsumption(ResourceScope.Machine)]
            get
            {
                if(File.Exists(PrecompiledAssemblyPath))
                    return Assembly.LoadFrom(PrecompiledAssemblyPath);
                return null;
            }
        }
 
		// function to check if the class to be added to MOF is already present in repository
		// [Microsoft] VSUQFE#2248 (VSWhidbey 231885)
		bool IsClassAlreadyPresentInRepository(ManagementObject obj)
		{
			bool bRet = false;
			string ClassPathInRepository = MakeClassPath(NamespaceName, (string)obj.SystemProperties["__CLASS"].Value);
 
			if (DoesClassExist(ClassPathInRepository))
			{
				ManagementObject inst = new ManagementClass(ClassPathInRepository);
				bRet = inst.CompareTo(obj, ComparisonSettings.IgnoreCase | ComparisonSettings.IgnoreObjectSource);
			}
 
			return bRet;
		}
        string GenerateMof(string [] mofs)
        {
            return String.Concat(
                "//**************************************************************************\r\n",
                String.Format("//* {0}\r\n", DecoupledProviderInstanceName),
                String.Format("//* {0}\r\n", AssemblyUniqueIdentifier),
                "//**************************************************************************\r\n",
                "#pragma autorecover\r\n",
                EnsureNamespaceInMof(GlobalRegistrationNamespace),
                EnsureNamespaceInMof(NamespaceName),
 
                PragmaNamespace(GlobalRegistrationNamespace),
                GetMofFormat(new ManagementClass(GlobalInstrumentationClassPath)),
                GetMofFormat(new ManagementClass(GlobalRegistrationClassPath)),
                GetMofFormat(new ManagementClass(GlobalNamingClassPath)),
                GetMofFormat(new ManagementObject(GlobalRegistrationPath)),
 
                PragmaNamespace(NamespaceName),
                GetMofFormat(new ManagementClass(InstrumentationClassPath)),
                GetMofFormat(new ManagementClass(RegistrationClassPath)),
                GetMofFormat(new ManagementClass(DecoupledProviderClassPath)),
                GetMofFormat(new ManagementClass(ProviderClassPath)),
 
                GetMofFormat(new ManagementObject(ProviderPath)),
//                events.Count>0?GetMofFormat(new ManagementObject(EventProviderRegistrationPath)):"",
                GetMofFormat(new ManagementObject(EventProviderRegistrationPath)),
                GetMofFormat(new ManagementObject(InstanceProviderRegistrationPath)),
 
                String.Concat(mofs),
 
                GetMofFormat(new ManagementObject(RegistrationPath)) );
        }
 
        public void RegisterNonAssemblySpecificSchema(InstallContext installContext)
        {
            SecurityHelper.UnmanagedCode.Demand(); // Bug#112640 - Close off any potential use from anything but fully trusted code
            
            // Make sure the 'Client' key has the correct permissions
            WmiNetUtilsHelper.VerifyClientKey_f();
 
            InstallLogWrapper context = new InstallLogWrapper(installContext);
 
            EnsureNamespace(context, GlobalRegistrationNamespace);
 
            EnsureClassExists(context, GlobalInstrumentationClassPath, new ClassMaker(MakeGlobalInstrumentationClass));
 
            EnsureClassExists(context, GlobalRegistrationClassPath, new ClassMaker(MakeNamespaceRegistrationClass));
 
            EnsureClassExists(context, GlobalNamingClassPath, new ClassMaker(MakeNamingClass));
 
            EnsureNamespace(context, NamespaceName);
 
            EnsureClassExists(context, InstrumentationClassPath, new ClassMaker(MakeInstrumentationClass));
 
            EnsureClassExists(context, RegistrationClassPath, new ClassMaker(MakeRegistrationClass));
 
            // Make sure Hosting model is set correctly by default.  If not, we blow away the class definition
            try
            {
                ManagementClass cls = new ManagementClass(DecoupledProviderClassPath);
                if(cls["HostingModel"].ToString() != "Decoupled:Com")
                {
                    cls.Delete();
                }
            }
            catch(ManagementException e)
            {
                if(e.ErrorCode != ManagementStatus.NotFound)
                    throw e;
            }
 
            EnsureClassExists(context, DecoupledProviderClassPath, new ClassMaker(MakeDecoupledProviderClass));
 
            EnsureClassExists(context, ProviderClassPath, new ClassMaker(MakeProviderClass));
 
            if(!DoesInstanceExist(GlobalRegistrationPath))
                RegisterNamespaceAsInstrumented();
        }
 
              [ResourceExposure(ResourceScope.None),ResourceConsumption(ResourceScope.Machine,ResourceScope.Machine)]
		public void RegisterAssemblySpecificSchema()
		{
			SecurityHelper.UnmanagedCode.Demand(); // Bug#112640 - Close off any potential use from anything but fully trusted code
 
			Type[] types = InstrumentedAttribute.GetInstrumentedTypes(assembly);
			StringCollection events = new StringCollection();
			StringCollection instances = new StringCollection();
			StringCollection abstracts = new StringCollection();
			string[] mofs = new string[types.Length];
			CodeWriter code = new CodeWriter();
			ReferencesCollection references = new ReferencesCollection();
 
			// Add the node with all the 'using' statements at the top
			code.AddChild(references.UsingCode);
			references.Add(typeof(Object));
			references.Add(typeof(ManagementClass));
			references.Add(typeof(Marshal));
			references.Add(typeof(System.Security.SuppressUnmanagedCodeSecurityAttribute));
			references.Add(typeof(System.Reflection.FieldInfo));
			references.Add(typeof(Hashtable));
 
			// Add a blank line
			code.Line();
 
			// Add master converter class
			CodeWriter codeWMIConverter = code.AddChild("public class WMINET_Converter");
            
			// Add master map of types to converters
			codeWMIConverter.Line("public static Hashtable mapTypeToConverter = new Hashtable();");
          
			// Add master CCTOR
			CodeWriter codeCCTOR = codeWMIConverter.AddChild("static WMINET_Converter()");
 
			// Make mapping of types to converter class names
			Hashtable mapTypeToConverterClassName = new Hashtable();
 
			for(int i=0;i<types.Length;i++)
				mapTypeToConverterClassName[types[i]] = "ConvertClass_" + i;
 
			// [Microsoft] VSUQFE#2248 (VSWhidbey 231885)
			bool bSchemaToBeCompared = IsSchemaToBeCompared();
			bool bNewClassToCompile = false;
 
			// Mof compilation is dictated by, whether the assembly is registered as instrumented or not
			if (bSchemaToBeCompared == false)
			{
				bNewClassToCompile = !IsAssemblyRegistered();
			}
 
			for(int i=0;i<types.Length;i++)
			{
				SchemaMapping mapping = new SchemaMapping(types[i], this, mapTypeToConverterClassName);
 
				codeCCTOR.Line(String.Format("mapTypeToConverter[typeof({0})] = typeof({1});", mapping.ClassType.FullName.Replace('+', '.'), mapping.CodeClassName));  // bug#92918 - watch for nested classes
				// [Microsoft] VSUQFE#2248 (VSWhidbey 231885)
				if (bSchemaToBeCompared == true && IsClassAlreadyPresentInRepository(mapping.NewClass) == false)
				{
					bNewClassToCompile = true;
				}
 
				ReplaceClassIfNecessary(mapping.ClassPath, mapping.NewClass);
 
				mofs[i] = GetMofFormat(mapping.NewClass);
				code.AddChild(mapping.Code);
				switch(mapping.InstrumentationType)
				{
					case InstrumentationType.Event:
						events.Add(mapping.ClassName);
						break;
 
					case InstrumentationType.Instance:
						instances.Add(mapping.ClassName);
						break;
 
					case InstrumentationType.Abstract:
						abstracts.Add(mapping.ClassName);
						break;
 
					default:
						break;
				}
			}
 
			RegisterAssemblySpecificDecoupledProviderInstance();
			RegisterProviderAsEventProvider(events);
			RegisterProviderAsInstanceProvider();
			RegisterAssemblyAsInstrumented();
			Directory.CreateDirectory(DataDirectory);
			using(StreamWriter log = new StreamWriter(CodePath, false, Encoding.Unicode))
			{
				log.WriteLine(code);
				log.WriteLine(iwoaDef+"new ManagementPath(@\""+this.NamespaceName+"\")"+iwoaDefEnd);
			}
 
			// Always generate the MOF in unicode
			using(StreamWriter log = new StreamWriter(MofPath, false, Encoding.Unicode))
			{
				log.WriteLine(GenerateMof(mofs));
			}
 
			// [Microsoft] VSUQFE#2248 (VSWhidbey 231885)
			// Write the mof to a file and compile it only if there are any new classes , apart from
			// what is there in the repository
			if (bNewClassToCompile == true)
			{
			RegisterSchemaUsingMofcomp ( MofPath ) ;
			//WMICapabilities.AddAutorecoverMof(MofPath);
		}
		}
        
		const string iwoaDef =
@"class IWOA
{
protected const string DllName = ""wminet_utils.dll"";
protected const string EntryPointName = ""UFunc"";
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""GetPropertyHandle"")] public static extern int GetPropertyHandle_f27(int vFunc, IntPtr pWbemClassObject, [In][MarshalAs(UnmanagedType.LPWStr)]  string   wszPropertyName, [Out] out Int32 pType, [Out] out Int32 plHandle);
//[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""WritePropertyValue"")] public static extern int WritePropertyValue_f28(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [In] Int32 lNumBytes, [In] ref Byte aData);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""ReadPropertyValue"")] public static extern int ReadPropertyValue_f29(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [In] Int32 lBufferSize, [Out] out Int32 plNumBytes, [Out] out Byte aData);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""ReadDWORD"")] public static extern int ReadDWORD_f30(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [Out] out UInt32 pdw);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""WriteDWORD"")] public static extern int WriteDWORD_f31(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [In] UInt32 dw);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""ReadQWORD"")] public static extern int ReadQWORD_f32(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [Out] out UInt64 pqw);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""WriteQWORD"")] public static extern int WriteQWORD_f33(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [In] UInt64 pw);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""GetPropertyInfoByHandle"")] public static extern int GetPropertyInfoByHandle_f34(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [Out][MarshalAs(UnmanagedType.BStr)]  out string   pstrName, [Out] out Int32 pType);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""Lock"")] public static extern int Lock_f35(int vFunc, IntPtr pWbemClassObject, [In] Int32 lFlags);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""Unlock"")] public static extern int Unlock_f36(int vFunc, IntPtr pWbemClassObject, [In] Int32 lFlags);
 
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""Put"")] public static extern int Put_f5(int vFunc, IntPtr pWbemClassObject, [In][MarshalAs(UnmanagedType.LPWStr)]  string   wszName, [In] Int32 lFlags, [In] ref object pVal, [In] Int32 Type);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""WritePropertyValue"")] public static extern int WritePropertyValue_f28(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [In] Int32 lNumBytes, [In][MarshalAs(UnmanagedType.LPWStr)] string str);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""WritePropertyValue"")] public static extern int WritePropertyValue_f28(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [In] Int32 lNumBytes, [In] ref Byte n);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""WritePropertyValue"")] public static extern int WritePropertyValue_f28(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [In] Int32 lNumBytes, [In] ref SByte n);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""WritePropertyValue"")] public static extern int WritePropertyValue_f28(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [In] Int32 lNumBytes, [In] ref Int16 n);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""WritePropertyValue"")] public static extern int WritePropertyValue_f28(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [In] Int32 lNumBytes, [In] ref UInt16 n);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""WritePropertyValue"", CharSet=CharSet.Unicode)] public static extern int WritePropertyValue_f28(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [In] Int32 lNumBytes, [In] ref Char c);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""WriteDWORD"")] public static extern int WriteDWORD_f31(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [In] Int32 dw);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""WriteSingle"")] public static extern int WriteDWORD_f31(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [In] Single dw);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""WriteQWORD"")] public static extern int WriteQWORD_f33(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [In] Int64 pw);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""WriteDouble"")] public static extern int WriteQWORD_f33(int vFunc, IntPtr pWbemClassObject, [In] Int32 lHandle, [In] Double pw);
[SuppressUnmanagedCodeSecurity, DllImport(DllName, EntryPoint=""Clone"")] public static extern int Clone_f(int vFunc, IntPtr pWbemClassObject, [Out] out IntPtr ppCopy);
}
interface IWmiConverter
{
    void ToWMI(object obj);
    ManagementObject GetInstance();
}
class SafeAssign
{
    public static UInt16 boolTrue = 0xffff;
    public static UInt16 boolFalse = 0;
    static Hashtable validTypes = new Hashtable();
    static SafeAssign()
    {
        validTypes.Add(typeof(SByte), null);
        validTypes.Add(typeof(Byte), null);
        validTypes.Add(typeof(Int16), null);
        validTypes.Add(typeof(UInt16), null);
        validTypes.Add(typeof(Int32), null);
        validTypes.Add(typeof(UInt32), null);
        validTypes.Add(typeof(Int64), null);
        validTypes.Add(typeof(UInt64), null);
        validTypes.Add(typeof(Single), null);
        validTypes.Add(typeof(Double), null);
        validTypes.Add(typeof(Boolean), null);
        validTypes.Add(typeof(String), null);
        validTypes.Add(typeof(Char), null);
        validTypes.Add(typeof(DateTime), null);
        validTypes.Add(typeof(TimeSpan), null);
        validTypes.Add(typeof(ManagementObject), null);
        nullClass.SystemProperties [""__CLASS""].Value = ""nullInstance"";
    }
    public static object GetInstance(object o)
    {
        if(o is ManagementObject)
            return o;
        return null;
    }
    static ManagementClass nullClass = new ManagementClass(" ;
		
const string iwoaDefEnd =
			@");
    
    public static ManagementObject GetManagementObject(object o)
    {
        if(o != null && o is ManagementObject)
            return o as ManagementObject;
        // Must return empty instance
        return nullClass.CreateInstance();
    }
    public static object GetValue(object o)
    {
        Type t = o.GetType();
        if(t.IsArray)
            t = t.GetElementType();
        if(validTypes.Contains(t))
            return o;
        return null;
    }
    public static string WMITimeToString(DateTime dt)
    {
        TimeSpan ts = dt.Subtract(dt.ToUniversalTime());
        int diffUTC = (ts.Minutes + ts.Hours * 60);
        if(diffUTC >= 0)
            return String.Format(""{0:D4}{1:D2}{2:D2}{3:D2}{4:D2}{5:D2}.{6:D3}000+{7:D3}"", dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, dt.Millisecond, diffUTC);
        return String.Format(""{0:D4}{1:D2}{2:D2}{3:D2}{4:D2}{5:D2}.{6:D3}000-{7:D3}"", dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, dt.Millisecond, -diffUTC);
    }
    public static string WMITimeToString(TimeSpan ts)
    {
        return String.Format(""{0:D8}{1:D2}{2:D2}{3:D2}.{4:D3}000:000"", ts.Days, ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds);
    }
    public static string[] WMITimeArrayToStringArray(DateTime[] dates)
    {
        string[] strings = new string[dates.Length];
        for(int i=0;i<dates.Length;i++)
            strings[i] = WMITimeToString(dates[i]);
        return strings;
    }
    public static string[] WMITimeArrayToStringArray(TimeSpan[] timeSpans)
    {
        string[] strings = new string[timeSpans.Length];
        for(int i=0;i<timeSpans.Length;i++)
            strings[i] = WMITimeToString(timeSpans[i]);
        return strings;
    }
}
";
 
 
        ///////////////////////////////////////////
        // Functions that create instances for the
        // registration of various objects
        void RegisterNamespaceAsInstrumented()
        {
            ManagementClass registrationClass = new ManagementClass(GlobalRegistrationClassPath);
            ManagementObject inst = registrationClass.CreateInstance();
            inst["NamespaceName"] = NamespaceName;
            inst.Put();
        }
 
        void RegisterAssemblyAsInstrumented()
        {
            ManagementClass registrationClass = new ManagementClass(RegistrationClassPath);
            ManagementObject inst = registrationClass.CreateInstance();
            inst["Name"] = DecoupledProviderInstanceName;
            inst["RegisteredBuild"] = AssemblyUniqueIdentifier;
            inst["FullName"] = AssemblyName;
            inst["PathToAssembly"] = AssemblyPath;
            inst["Code"] = "";
            inst["Mof"] = "";
            inst.Put();
        }
 
        void RegisterAssemblySpecificDecoupledProviderInstance()
        {
            ManagementClass providerClass = new ManagementClass(ProviderClassPath);
            ManagementObject inst = providerClass.CreateInstance();
            inst["Name"] = DecoupledProviderInstanceName;
            inst["HostingModel"] = "Decoupled:Com"; // 
            if(null != SecurityDescriptor)
                inst["SecurityDescriptor"] = SecurityDescriptor;
            inst.Put();
        }
 
        string RegisterProviderAsEventProvider(StringCollection events)
        {
            // 
 
 
 
            ManagementClass providerRegistrationClass = new ManagementClass(EventProviderRegistrationClassPath);
            ManagementObject inst = providerRegistrationClass.CreateInstance();
            inst["provider"] = "\\\\.\\"+ProviderPath;
            string [] queries = new string[events.Count];
            int iCur = 0;
            foreach(string eventName in events)
                queries[iCur++] = "select * from "+eventName;
 
            inst["EventQueryList"] = queries;
            return inst.Put().Path;
        }
 
        string RegisterProviderAsInstanceProvider()
        {
            ManagementClass providerRegistrationClass = new ManagementClass(InstanceProviderRegistrationClassPath);
            ManagementObject inst = providerRegistrationClass.CreateInstance();
            inst["provider"] = "\\\\.\\"+ProviderPath;
            inst["SupportsGet"] = true;
            inst["SupportsEnumeration"] = true;
            return inst.Put().Path;
        }
 
        ///////////////////////////////////////////
        // Functions that create Class prototypes
 
        delegate ManagementClass ClassMaker();
 
        ManagementClass MakeNamingClass()
        {
            ManagementClass baseClass = new ManagementClass(GlobalInstrumentationClassPath);
            ManagementClass newClass = baseClass.Derive(NamingClassName);
            newClass.Qualifiers.Add("abstract", true);
            PropertyDataCollection props = newClass.Properties;
            props.Add("InstrumentedAssembliesClassName", InstrumentedAssembliesClassName, CimType.String);
            return newClass;
        }
        
        ManagementClass MakeInstrumentationClass()
        {
            ManagementClass newClass = new ManagementClass(NamespaceName, "", null);
            newClass.SystemProperties ["__CLASS"].Value = InstrumentationClassName;
            newClass.Qualifiers.Add("abstract", true);
            return newClass;
        }
 
        ManagementClass MakeGlobalInstrumentationClass()
        {
            ManagementClass newClass = new ManagementClass(GlobalWmiNetNamespace, "", null);
            newClass.SystemProperties ["__CLASS"].Value = InstrumentationClassName;
            newClass.Qualifiers.Add("abstract", true);
            return newClass;
        }
 
        ManagementClass MakeRegistrationClass()
        {
            ManagementClass baseClass = new ManagementClass(InstrumentationClassPath);
            ManagementClass newClass = baseClass.Derive(InstrumentedAssembliesClassName);
            PropertyDataCollection props = newClass.Properties;
            props.Add("Name", CimType.String, false);
            PropertyData prop = props["Name"];
            prop.Qualifiers.Add("key", true);
            props.Add("RegisteredBuild", CimType.String, false);
            props.Add("FullName", CimType.String, false);
            props.Add("PathToAssembly", CimType.String, false);
            props.Add("Code", CimType.String, false);
            props.Add("Mof", CimType.String, false);
            return newClass;
        }
 
        ManagementClass MakeNamespaceRegistrationClass()
        {
            ManagementClass baseClass = new ManagementClass(GlobalInstrumentationClassPath);
            ManagementClass newClass = baseClass.Derive(InstrumentedNamespacesClassName);
            PropertyDataCollection props = newClass.Properties;
            props.Add("NamespaceName", CimType.String, false);
            PropertyData prop = props["NamespaceName"];
            prop.Qualifiers.Add("key", true);
            return newClass;
        }
 
        ManagementClass MakeDecoupledProviderClass()
        {
            ManagementClass baseClass = new ManagementClass(Win32ProviderClassPath);
            ManagementClass newClass = baseClass.Derive(DecoupledProviderClassName);
            PropertyDataCollection props = newClass.Properties;
            props.Add("HostingModel", "Decoupled:Com", CimType.String);
            props.Add("SecurityDescriptor", CimType.String, false);
            props.Add("Version", 1, CimType.UInt32);
            props["CLSID"].Value = DecoupledProviderCLSID;
            return newClass;
        }
 
        ManagementClass MakeProviderClass()
        {
            ManagementClass baseClass = new ManagementClass(DecoupledProviderClassPath);
            ManagementClass newClass = baseClass.Derive(ProviderClassName);
            PropertyDataCollection props = newClass.Properties;
            props.Add("Assembly", CimType.String, false);
            return newClass;
        }
 
        ///////////////////////////////////////////
        // WMI Helper Functions
 
		//
		// [RAID#143683, marioh] This method was added to register the instrumentation schema by forking 
		// mofcomp.exe rather than simply writing it directly to the repository. The reason for this is
		// a change in .NET server that requires MOF files to be compiled using mofcomp in order to be
		// autorecoverable. It is no longer possible to do by directly accessing the autorecover key in the
		// registry (due to security considerations).
		//
		// Note: Due to code design, we are using mofcomp IN ADDITION to writing directly to the repository.
		//
              [ResourceExposure(ResourceScope.None),ResourceConsumption(ResourceScope.Machine,ResourceScope.Machine)]
		static void RegisterSchemaUsingMofcomp ( string mofPath )
		{
			System.Diagnostics.ProcessStartInfo processInfo = new System.Diagnostics.ProcessStartInfo ( ) ;
			processInfo.Arguments = mofPath ;
			processInfo.FileName = WMICapabilities.InstallationDirectory+"\\mofcomp.exe" ;
			processInfo.UseShellExecute = false ;
			processInfo.RedirectStandardOutput = true ;
 
			//
			// [PS#170134, marioh] Make sure no command shell window is displayed when invoking mofcomp
			//
			processInfo.CreateNoWindow = true ;				
 
			System.Diagnostics.Process proc = System.Diagnostics.Process.Start ( processInfo ) ;
			proc.WaitForExit ( ) ;
		}
 
        static void EnsureNamespace(string baseNamespace, string childNamespaceName)
        {
            if(!DoesInstanceExist(baseNamespace + ":__NAMESPACE.Name=\""+childNamespaceName+"\""))
            {
                ManagementClass namespaceClass = new ManagementClass(baseNamespace + ":__NAMESPACE");
                ManagementObject inst = namespaceClass.CreateInstance();
                inst["Name"] = childNamespaceName;
                inst.Put();
            }
        }
 
        static void EnsureNamespace(InstallLogWrapper context, string namespaceName)
        {
            context.LogMessage(RC.GetString("NAMESPACE_ENSURE")+ " " +namespaceName);
 
            string fullNamespace = null;
            foreach(string name in namespaceName.Split(new char[] {'\\'}))
            {
                if(fullNamespace == null)
                {
                    fullNamespace = name;
                    continue;
                }
                EnsureNamespace(fullNamespace, name);
                fullNamespace += "\\" + name;
            }
        }
 
        static void EnsureClassExists(InstallLogWrapper context, string classPath, ClassMaker classMakerFunction)
        {
            try
            {
                context.LogMessage(RC.GetString("CLASS_ENSURE") + " " +classPath);
                ManagementClass theClass = new ManagementClass(classPath);
                theClass.Get();
            }
            catch(ManagementException e)
            {
                if(e.ErrorCode == ManagementStatus.NotFound)
                {
                    // The class does not exist.  Create it.
                    context.LogMessage(RC.GetString("CLASS_ENSURECREATE")+ " " +classPath);
                    ManagementClass theClass = classMakerFunction();
                    theClass.Put();
                }
                else
                    throw e;
            }
        }
 
        static bool DoesInstanceExist(string objectPath)
        {
            bool exists = false;
            try
            {
                ManagementObject inst = new ManagementObject(objectPath);
                inst.Get();
                exists = true;
            }
            catch(ManagementException e)
            {
                if(     ManagementStatus.InvalidNamespace != e.ErrorCode
                    &&  ManagementStatus.InvalidClass != e.ErrorCode
                    &&  ManagementStatus.NotFound != e.ErrorCode
                    )
                    throw e;
            }
            return exists;
        }
 
		static bool DoesClassExist(string objectPath)
		{
			bool exists = false;
 
			try
			{
				ManagementObject cls = new ManagementClass(objectPath);
 
				cls.Get();
				exists = true;
			}
			catch (ManagementException e)
			{
				if (ManagementStatus.InvalidNamespace != e.ErrorCode && ManagementStatus.InvalidClass != e.ErrorCode && ManagementStatus.NotFound != e.ErrorCode)
                    throw e;
            }
            return exists;
        }
 
        /// <summary>
        /// Given a class path, this function will return the ManagementClass
        /// if it exists, or null if it does not.
        /// </summary>
        /// <param name="classPath">WMI path to Class</param>
        /// <returns></returns>
        static ManagementClass SafeGetClass(string classPath)
        {
            ManagementClass theClass = null;
            try
            {
                ManagementClass existingClass = new ManagementClass(classPath);
                existingClass.Get();
                theClass = existingClass;
            }
            catch(ManagementException e)
            {
                if(e.ErrorCode != ManagementStatus.NotFound)
                    throw e;
            }
            return theClass;
        }
 
        /// <summary>
        /// Given a class path, and a ManagementClass class definition, this
        /// function will create the class if it does not exist, replace the
        /// class if it exists but is different, or do nothing if the class
        /// exists and is identical.  This is useful for performance reasons
        /// since it can be expensive to delete an existing class and replace
        /// it.
        /// </summary>
        /// <param name="classPath">WMI path to class</param>
        /// <param name="newClass">Class to create or replace</param>
        static void ReplaceClassIfNecessary(string classPath, ManagementClass newClass)
        {
            try
            {
                ManagementClass oldClass = SafeGetClass(classPath);
                if(null == oldClass)
                    newClass.Put();
                else
                {
                    // 
 
                    if(newClass.GetText(TextFormat.Mof) != oldClass.GetText(TextFormat.Mof))
                    {
                        // 
                        oldClass.Delete();
                        newClass.Put();
                    }
                }
            }
            catch(ManagementException e)
            {
				string strformat = RC.GetString("CLASS_NOTREPLACED_EXCEPT") + "\r\n{0}\r\n{1}";
                throw new ArgumentException(String.Format(strformat, classPath, newClass.GetText(TextFormat.Mof)), e);
            }
        }
 
        static string GetMofFormat(ManagementObject obj)
        {
            return obj.GetText(TextFormat.Mof).Replace("\n", "\r\n") + "\r\n";
        }
 
        static string PragmaNamespace(string namespaceName)
        {
            return String.Format("#pragma namespace(\"\\\\\\\\.\\\\{0}\")\r\n\r\n", namespaceName.Replace("\\", "\\\\"));
        }
 
        static string EnsureNamespaceInMof(string baseNamespace, string childNamespaceName)
        {
            return String.Format("{0}instance of __Namespace\r\n{{\r\n  Name = \"{1}\";\r\n}};\r\n\r\n", PragmaNamespace(baseNamespace), childNamespaceName);
        }
 
        static string EnsureNamespaceInMof(string namespaceName)
        {
            string mof="";
            string fullNamespace = null;
            foreach(string name in namespaceName.Split(new char[] {'\\'}))
            {
                if(fullNamespace == null)
                {
                    fullNamespace = name;
                    continue;
                }
                mof+=EnsureNamespaceInMof(fullNamespace, name);
                fullNamespace += "\\" + name;
            }
            return mof;
        }
    }
}