Fixed Issue 387. The new implementation does not try to start a ring 0 driver that already exists, but could not be opened. It tries to delete the driver and install it new. The driver is now stored temporarily in the application folder. The driver is not correctly removed on system shutdown.
3 This Source Code Form is subject to the terms of the Mozilla Public
4 License, v. 2.0. If a copy of the MPL was not distributed with this
5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 Copyright (C) 2010 Michael Möller <mmoeller@openhardwaremonitor.org>
12 using System.Runtime.InteropServices;
13 using System.Reflection;
15 namespace OpenHardwareMonitor.Hardware {
16 internal static class Opcode {
18 private static IntPtr codeBuffer;
19 private static ulong size;
21 public static void Open() {
22 int p = (int)Environment.OSVersion.Platform;
26 if (IntPtr.Size == 4) {
32 if ((p == 4) || (p == 128)) { // Unix
33 cpuidCode = CPUID_64_LINUX;
35 cpuidCode = CPUID_64_WINDOWS;
39 size = (ulong)(rdtscCode.Length + cpuidCode.Length);
41 if ((p == 4) || (p == 128)) { // Unix
43 Assembly.Load("Mono.Posix, Version=2.0.0.0, Culture=neutral, " +
44 "PublicKeyToken=0738eb9f132ed756");
46 Type syscall = assembly.GetType("Mono.Unix.Native.Syscall");
47 MethodInfo mmap = syscall.GetMethod("mmap");
49 Type mmapProts = assembly.GetType("Mono.Unix.Native.MmapProts");
50 object mmapProtsParam = Enum.ToObject(mmapProts,
51 (int)mmapProts.GetField("PROT_READ").GetValue(null) |
52 (int)mmapProts.GetField("PROT_WRITE").GetValue(null) |
53 (int)mmapProts.GetField("PROT_EXEC").GetValue(null));
55 Type mmapFlags = assembly.GetType("Mono.Unix.Native.MmapFlags");
56 object mmapFlagsParam = Enum.ToObject(mmapFlags,
57 (int)mmapFlags.GetField("MAP_ANONYMOUS").GetValue(null) |
58 (int)mmapFlags.GetField("MAP_PRIVATE").GetValue(null));
60 codeBuffer = (IntPtr)mmap.Invoke(null, new object[] { IntPtr.Zero,
61 size, mmapProtsParam, mmapFlagsParam, -1, 0 });
63 codeBuffer = NativeMethods.VirtualAlloc(IntPtr.Zero,
64 (UIntPtr)size, AllocationType.COMMIT | AllocationType.RESERVE,
65 MemoryProtection.EXECUTE_READWRITE);
68 Marshal.Copy(rdtscCode, 0, codeBuffer, rdtscCode.Length);
70 Rdtsc = Marshal.GetDelegateForFunctionPointer(
71 codeBuffer, typeof(RdtscDelegate)) as RdtscDelegate;
73 IntPtr cpuidAddress = (IntPtr)((long)codeBuffer + rdtscCode.Length);
74 Marshal.Copy(cpuidCode, 0, cpuidAddress, cpuidCode.Length);
76 Cpuid = Marshal.GetDelegateForFunctionPointer(
77 cpuidAddress, typeof(CpuidDelegate)) as CpuidDelegate;
80 public static void Close() {
84 int p = (int)Environment.OSVersion.Platform;
85 if ((p == 4) || (p == 128)) { // Unix
87 Assembly.Load("Mono.Posix, Version=2.0.0.0, Culture=neutral, " +
88 "PublicKeyToken=0738eb9f132ed756");
90 Type syscall = assembly.GetType("Mono.Unix.Native.Syscall");
91 MethodInfo munmap = syscall.GetMethod("munmap");
92 munmap.Invoke(null, new object[] { codeBuffer, size });
95 NativeMethods.VirtualFree(codeBuffer, UIntPtr.Zero,
100 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
101 public delegate ulong RdtscDelegate();
103 public static RdtscDelegate Rdtsc;
105 // unsigned __int64 __stdcall rdtsc() {
109 private static readonly byte[] RDTSC_32 = new byte[] {
114 private static readonly byte[] RDTSC_64 = new byte[] {
116 0x48, 0xC1, 0xE2, 0x20, // shl rdx, 20h
117 0x48, 0x0B, 0xC2, // or rax, rdx
121 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
122 public delegate bool CpuidDelegate(uint index, uint ecxValue,
123 out uint eax, out uint ebx, out uint ecx, out uint edx);
125 public static CpuidDelegate Cpuid;
128 // void __stdcall cpuidex(unsigned int index, unsigned int ecxValue,
129 // unsigned int* eax, unsigned int* ebx, unsigned int* ecx,
130 // unsigned int* edx)
133 // __cpuidex(info, index, ecxValue);
140 private static readonly byte[] CPUID_32 = new byte[] {
142 0x8B, 0xEC, // mov ebp, esp
143 0x83, 0xEC, 0x10, // sub esp, 10h
144 0x8B, 0x45, 0x08, // mov eax, dword ptr [ebp+8]
145 0x8B, 0x4D, 0x0C, // mov ecx, dword ptr [ebp+0Ch]
149 0x8D, 0x75, 0xF0, // lea esi, [info]
150 0x89, 0x06, // mov dword ptr [esi],eax
151 0x8B, 0x45, 0x10, // mov eax, dword ptr [eax]
152 0x89, 0x5E, 0x04, // mov dword ptr [esi+4], ebx
153 0x89, 0x4E, 0x08, // mov dword ptr [esi+8], ecx
154 0x89, 0x56, 0x0C, // mov dword ptr [esi+0Ch], edx
155 0x8B, 0x4D, 0xF0, // mov ecx, dword ptr [info]
156 0x89, 0x08, // mov dword ptr [eax], ecx
157 0x8B, 0x45, 0x14, // mov eax, dword ptr [ebx]
158 0x8B, 0x4D, 0xF4, // mov ecx, dword ptr [ebp-0Ch]
159 0x89, 0x08, // mov dword ptr [eax], ecx
160 0x8B, 0x45, 0x18, // mov eax, dword ptr [ecx]
161 0x8B, 0x4D, 0xF8, // mov ecx, dword ptr [ebp-8]
162 0x89, 0x08, // mov dword ptr [eax], ecx
163 0x8B, 0x45, 0x1C, // mov eax, dword ptr [edx]
164 0x8B, 0x4D, 0xFC, // mov ecx, dword ptr [ebp-4]
166 0x89, 0x08, // mov dword ptr [eax], ecx
169 0xC2, 0x18, 0x00 // ret 18h
172 private static readonly byte[] CPUID_64_WINDOWS = new byte[] {
173 0x48, 0x89, 0x5C, 0x24, 0x08, // mov qword ptr [rsp+8], rbx
174 0x8B, 0xC1, // mov eax, ecx
175 0x8B, 0xCA, // mov ecx, edx
177 0x41, 0x89, 0x00, // mov dword ptr [r8], eax
178 0x48, 0x8B, 0x44, 0x24, 0x28, // mov rax, qword ptr [rsp+28h]
179 0x41, 0x89, 0x19, // mov dword ptr [r9], ebx
180 0x48, 0x8B, 0x5C, 0x24, 0x08, // mov rbx, qword ptr [rsp+8]
181 0x89, 0x08, // mov dword ptr [rax], ecx
182 0x48, 0x8B, 0x44, 0x24, 0x30, // mov rax, qword ptr [rsp+30h]
183 0x89, 0x10, // mov dword ptr [rax], edx
187 private static readonly byte[] CPUID_64_LINUX = new byte[] {
188 0x49, 0x89, 0xD2, // mov r10, rdx
189 0x49, 0x89, 0xCB, // mov r11, rcx
191 0x89, 0xF8, // mov eax, edi
192 0x89, 0xF1, // mov ecx, esi
194 0x41, 0x89, 0x02, // mov dword ptr [r10], eax
195 0x41, 0x89, 0x1B, // mov dword ptr [r11], ebx
196 0x41, 0x89, 0x08, // mov dword ptr [r8], ecx
197 0x41, 0x89, 0x11, // mov dword ptr [r9], edx
202 public static bool CpuidTx(uint index, uint ecxValue,
203 out uint eax, out uint ebx, out uint ecx, out uint edx,
204 ulong threadAffinityMask) {
206 ulong mask = ThreadAffinity.Set(threadAffinityMask);
209 eax = ebx = ecx = edx = 0;
213 Cpuid(index, ecxValue, out eax, out ebx, out ecx, out edx);
215 ThreadAffinity.Set(mask);
220 public enum AllocationType : uint {
224 LARGE_PAGES = 0x20000000,
227 WRITE_WATCH = 0x200000
231 public enum MemoryProtection : uint {
234 EXECUTE_READWRITE = 0x40,
235 EXECUTE_WRITECOPY = 0x80,
246 public enum FreeType {
251 private static class NativeMethods {
252 private const string KERNEL = "kernel32.dll";
254 [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
255 public static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize,
256 AllocationType flAllocationType, MemoryProtection flProtect);
258 [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
259 public static extern bool VirtualFree(IntPtr lpAddress, UIntPtr dwSize,
260 FreeType dwFreeType);