Hardware/PInvokeDelegateFactory.cs
author moel.mich
Sat, 31 Dec 2011 17:31:04 +0000
changeset 324 c6ee430d6995
parent 167 b7cc9d09aefe
child 344 3145aadca3d2
permissions -rw-r--r--
Modified and extended version of the patch v4 by Roland Reinl (see Issue 256). Main differences to the original patch: DeviceIoControl refactorings removed, SmartAttribute is now descriptive only and does not hold any state, report is written as one 80 columns table, sensors are created only for meaningful values and without duplicates (remaining life, temperatures, host writes and reads). Also the current implementation should really preserve all the functionality of the old system. Additionally there is now a simple SMART devices emulation class (DebugSmart) that can be used in place of WindowsSmart for testing with reported data.
moel@165
     1
/*
moel@165
     2
  
moel@165
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@165
     4
moel@165
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@165
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@165
     7
  the License. You may obtain a copy of the License at
moel@165
     8
 
moel@165
     9
  http://www.mozilla.org/MPL/
moel@165
    10
moel@165
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@165
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@165
    13
  for the specific language governing rights and limitations under the License.
moel@165
    14
moel@165
    15
  The Original Code is the Open Hardware Monitor code.
moel@165
    16
moel@165
    17
  The Initial Developer of the Original Code is 
moel@165
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@165
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2010
moel@165
    20
  the Initial Developer. All Rights Reserved.
moel@165
    21
moel@165
    22
  Contributor(s):
moel@165
    23
moel@165
    24
  Alternatively, the contents of this file may be used under the terms of
moel@165
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@165
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@165
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@165
    28
  of those above. If you wish to allow use of your version of this file only
moel@165
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@165
    30
  use your version of this file under the terms of the MPL, indicate your
moel@165
    31
  decision by deleting the provisions above and replace them with the notice
moel@165
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@165
    33
  the provisions above, a recipient may use your version of this file under
moel@165
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@165
    35
 
moel@165
    36
*/
moel@165
    37
moel@165
    38
using System;
moel@165
    39
using System.Collections.Generic;
moel@165
    40
using System.Reflection;
moel@165
    41
using System.Reflection.Emit;
moel@165
    42
using System.Runtime.InteropServices;
moel@165
    43
moel@165
    44
namespace OpenHardwareMonitor.Hardware {
moel@165
    45
moel@195
    46
  internal static class PInvokeDelegateFactory {
moel@165
    47
moel@195
    48
    private static readonly ModuleBuilder moduleBuilder = 
moel@167
    49
      AppDomain.CurrentDomain.DefineDynamicAssembly(
moel@167
    50
        new AssemblyName("PInvokeDelegateFactoryInternalAssembly"),
moel@167
    51
        AssemblyBuilderAccess.Run).DefineDynamicModule(
moel@167
    52
        "PInvokeDelegateFactoryInternalModule");
moel@165
    53
moel@195
    54
    private static readonly IDictionary<DllImportAttribute, Type> wrapperTypes =
moel@165
    55
      new Dictionary<DllImportAttribute, Type>();
moel@165
    56
moel@165
    57
    public static void CreateDelegate<T>(DllImportAttribute dllImportAttribute,
moel@165
    58
      out T newDelegate) where T : class 
moel@165
    59
    {
moel@165
    60
      Type wrapperType;
moel@165
    61
      wrapperTypes.TryGetValue(dllImportAttribute, out wrapperType);
moel@165
    62
moel@165
    63
      if (wrapperType == null) {
moel@165
    64
        wrapperType = CreateWrapperType(typeof(T), dllImportAttribute);
moel@165
    65
        wrapperTypes.Add(dllImportAttribute, wrapperType);
moel@165
    66
      }
moel@165
    67
moel@165
    68
      newDelegate = Delegate.CreateDelegate(typeof(T), wrapperType,
moel@165
    69
        dllImportAttribute.EntryPoint) as T;
moel@165
    70
    }
moel@165
    71
moel@165
    72
moel@165
    73
    private static Type CreateWrapperType(Type delegateType,
moel@165
    74
      DllImportAttribute dllImportAttribute) {
moel@165
    75
moel@165
    76
      TypeBuilder typeBuilder = moduleBuilder.DefineType(
moel@165
    77
        "PInvokeDelegateFactoryInternalWrapperType" + wrapperTypes.Count);
moel@165
    78
moel@165
    79
      MethodInfo methodInfo = delegateType.GetMethod("Invoke");
moel@165
    80
moel@165
    81
      ParameterInfo[] parameterInfos = methodInfo.GetParameters();
moel@165
    82
      int parameterCount = parameterInfos.GetLength(0);
moel@165
    83
moel@165
    84
      Type[] parameterTypes = new Type[parameterCount];
moel@165
    85
      for (int i = 0; i < parameterCount; i++)
moel@165
    86
        parameterTypes[i] = parameterInfos[i].ParameterType;
moel@165
    87
moel@165
    88
      MethodBuilder methodBuilder = typeBuilder.DefinePInvokeMethod(
moel@165
    89
        dllImportAttribute.EntryPoint, dllImportAttribute.Value,
moel@165
    90
        MethodAttributes.Public | MethodAttributes.Static |
moel@165
    91
        MethodAttributes.PinvokeImpl, CallingConventions.Standard,
moel@165
    92
        methodInfo.ReturnType, parameterTypes,
moel@165
    93
        dllImportAttribute.CallingConvention,
moel@165
    94
        dllImportAttribute.CharSet);
moel@165
    95
moel@165
    96
      foreach (ParameterInfo parameterInfo in parameterInfos)
moel@165
    97
        methodBuilder.DefineParameter(parameterInfo.Position + 1,
moel@165
    98
          parameterInfo.Attributes, parameterInfo.Name);
moel@165
    99
moel@165
   100
      if (dllImportAttribute.PreserveSig)
moel@165
   101
        methodBuilder.SetImplementationFlags(MethodImplAttributes.PreserveSig);
moel@165
   102
moel@165
   103
      return typeBuilder.CreateType();
moel@165
   104
    }
moel@165
   105
  }
moel@165
   106
}