# HG changeset patch
# User moel.mich
# Date 1264545468 0
# Node ID 361e324a0ed4bbc6713cb21ca1a7f9fae588d806
# Parent  77e062628ef5848ff6c5abaa1a052918b1507559
Initial commit.

diff -r 77e062628ef5 -r 361e324a0ed4 External/Aga.Controls.dll
Binary file External/Aga.Controls.dll has changed
diff -r 77e062628ef5 -r 361e324a0ed4 External/WinRing0.dll
Binary file External/WinRing0.dll has changed
diff -r 77e062628ef5 -r 361e324a0ed4 External/WinRing0.sys
Binary file External/WinRing0.sys has changed
diff -r 77e062628ef5 -r 361e324a0ed4 External/WinRing0.vxd
Binary file External/WinRing0.vxd has changed
diff -r 77e062628ef5 -r 361e324a0ed4 External/WinRing0x64.dll
Binary file External/WinRing0x64.dll has changed
diff -r 77e062628ef5 -r 361e324a0ed4 External/WinRing0x64.sys
Binary file External/WinRing0x64.sys has changed
diff -r 77e062628ef5 -r 361e324a0ed4 GUI/AboutBox.Designer.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI/AboutBox.Designer.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,214 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+namespace OpenHardwareMonitor.GUI {
+  partial class AboutBox {
+    /// <summary>
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary>
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Windows Form Designer generated code
+
+    /// <summary>
+    /// Required method for Designer support - do not modify
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutBox));
+      this.okButton = new System.Windows.Forms.Button();
+      this.pictureBox1 = new System.Windows.Forms.PictureBox();
+      this.label1 = new System.Windows.Forms.Label();
+      this.label2 = new System.Windows.Forms.Label();
+      this.label3 = new System.Windows.Forms.Label();
+      this.label4 = new System.Windows.Forms.Label();
+      this.linkLabel = new System.Windows.Forms.LinkLabel();
+      this.label5 = new System.Windows.Forms.Label();
+      this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
+      ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
+      this.flowLayoutPanel1.SuspendLayout();
+      this.SuspendLayout();
+      // 
+      // okButton
+      // 
+      this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+      this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+      this.okButton.Location = new System.Drawing.Point(305, 142);
+      this.okButton.Name = "okButton";
+      this.okButton.Size = new System.Drawing.Size(87, 27);
+      this.okButton.TabIndex = 0;
+      this.okButton.Text = "OK";
+      this.okButton.UseVisualStyleBackColor = true;
+      // 
+      // pictureBox1
+      // 
+      this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));
+      this.pictureBox1.Location = new System.Drawing.Point(12, 13);
+      this.pictureBox1.Name = "pictureBox1";
+      this.pictureBox1.Size = new System.Drawing.Size(56, 56);
+      this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+      this.pictureBox1.TabIndex = 1;
+      this.pictureBox1.TabStop = false;
+      // 
+      // label1
+      // 
+      this.label1.AutoSize = true;
+      this.label1.Font = new System.Drawing.Font("Segoe UI", 11F, System.Drawing.FontStyle.Bold);
+      this.label1.Location = new System.Drawing.Point(85, 13);
+      this.label1.Margin = new System.Windows.Forms.Padding(12, 0, 12, 0);
+      this.label1.Name = "label1";
+      this.label1.Size = new System.Drawing.Size(179, 20);
+      this.label1.TabIndex = 2;
+      this.label1.Text = "Open Hardware Monitor";
+      // 
+      // label2
+      // 
+      this.label2.AutoSize = true;
+      this.label2.Location = new System.Drawing.Point(86, 54);
+      this.label2.Margin = new System.Windows.Forms.Padding(12, 0, 12, 0);
+      this.label2.Name = "label2";
+      this.label2.Size = new System.Drawing.Size(315, 15);
+      this.label2.TabIndex = 3;
+      this.label2.Text = "Copyright © 2009-2010 Michael Möller. All rights reserved.";
+      // 
+      // label3
+      // 
+      this.label3.AutoSize = true;
+      this.label3.Location = new System.Drawing.Point(86, 36);
+      this.label3.Margin = new System.Windows.Forms.Padding(12, 0, 12, 0);
+      this.label3.Name = "label3";
+      this.label3.Size = new System.Drawing.Size(90, 15);
+      this.label3.TabIndex = 4;
+      this.label3.Text = "Version 0.1 Beta";
+      // 
+      // label4
+      // 
+      this.label4.AutoSize = true;
+      this.label4.Location = new System.Drawing.Point(9, 95);
+      this.label4.Margin = new System.Windows.Forms.Padding(12, 0, 12, 0);
+      this.label4.Name = "label4";
+      this.label4.Size = new System.Drawing.Size(412, 15);
+      this.label4.TabIndex = 5;
+      this.label4.Text = "The source code is available under the terms of the Mozilla Public License 1.1";
+      // 
+      // linkLabel
+      // 
+      this.linkLabel.AutoSize = true;
+      this.linkLabel.Location = new System.Drawing.Point(145, 0);
+      this.linkLabel.Margin = new System.Windows.Forms.Padding(0, 0, 12, 0);
+      this.linkLabel.Name = "linkLabel";
+      this.linkLabel.Size = new System.Drawing.Size(176, 15);
+      this.linkLabel.TabIndex = 6;
+      this.linkLabel.TabStop = true;
+      this.linkLabel.Text = "Open Hardware Monitor Project";
+      this.linkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
+      // 
+      // label5
+      // 
+      this.label5.AutoSize = true;
+      this.label5.Location = new System.Drawing.Point(0, 0);
+      this.label5.Margin = new System.Windows.Forms.Padding(0, 0, 3, 0);
+      this.label5.Name = "label5";
+      this.label5.Size = new System.Drawing.Size(142, 15);
+      this.label5.TabIndex = 7;
+      this.label5.Text = "from the project website: ";
+      // 
+      // flowLayoutPanel1
+      // 
+      this.flowLayoutPanel1.AutoSize = true;
+      this.flowLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+      this.flowLayoutPanel1.Controls.Add(this.label5);
+      this.flowLayoutPanel1.Controls.Add(this.linkLabel);
+      this.flowLayoutPanel1.Location = new System.Drawing.Point(12, 115);
+      this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(12, 0, 12, 0);
+      this.flowLayoutPanel1.Name = "flowLayoutPanel1";
+      this.flowLayoutPanel1.Size = new System.Drawing.Size(333, 15);
+      this.flowLayoutPanel1.TabIndex = 8;
+      // 
+      // AboutBox
+      // 
+      this.AcceptButton = this.okButton;
+      this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.AutoSize = true;
+      this.ClientSize = new System.Drawing.Size(404, 182);
+      this.Controls.Add(this.flowLayoutPanel1);
+      this.Controls.Add(this.label4);
+      this.Controls.Add(this.label3);
+      this.Controls.Add(this.label2);
+      this.Controls.Add(this.label1);
+      this.Controls.Add(this.pictureBox1);
+      this.Controls.Add(this.okButton);
+      this.Font = new System.Drawing.Font("Segoe UI", 9F);
+      this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+      this.MaximizeBox = false;
+      this.MinimizeBox = false;
+      this.Name = "AboutBox";
+      this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+      this.Text = "About";
+      ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
+      this.flowLayoutPanel1.ResumeLayout(false);
+      this.flowLayoutPanel1.PerformLayout();
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private System.Windows.Forms.Button okButton;
+    private System.Windows.Forms.PictureBox pictureBox1;
+    private System.Windows.Forms.Label label1;
+    private System.Windows.Forms.Label label2;
+    private System.Windows.Forms.Label label3;
+    private System.Windows.Forms.Label label4;
+    private System.Windows.Forms.LinkLabel linkLabel;
+    private System.Windows.Forms.Label label5;
+    private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
+  }
+}
\ No newline at end of file
diff -r 77e062628ef5 -r 361e324a0ed4 GUI/AboutBox.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI/AboutBox.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,63 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace OpenHardwareMonitor.GUI {
+  public partial class AboutBox : Form {
+    public AboutBox() {
+      InitializeComponent();
+      this.Font = SystemFonts.MessageBoxFont;
+
+      linkLabel.Links.Remove(linkLabel.Links[0]);
+      linkLabel.Links.Add(0, linkLabel.Text.Length,
+        "http://openhardwaremonitor.org");
+
+    }
+
+    private void linkLabel1_LinkClicked(object sender, 
+      LinkLabelLinkClickedEventArgs e) {
+      Process.Start(new ProcessStartInfo(e.Link.LinkData.ToString()));
+    }
+
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 GUI/AboutBox.resources
Binary file GUI/AboutBox.resources has changed
diff -r 77e062628ef5 -r 361e324a0ed4 GUI/AboutBox.resx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI/AboutBox.resx	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="pictureBox1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADrwAAA68AZW8ckkAAA2KSURBVGhD7VnpU9RXFp2ZL6kkxiSVVBIVWRvoZhUVUUBA
+        FBdQgbCq4BKVycQyxl1UFsV9QRQQxIgR9wX33YiJOlHjxESjpmKSqtF8yX9x55z7fr+mUSfprvliTcWq
+        V02VSt9z77nn3nfeX/7y558/M/BnBv7/MtDYuFW2bKnH2SKb6jbJxo0bZe3atbJq9WpZuXKl1CxfLlXV
+        VbJ0aYWUly+WBQsWyLx582TOnDky65NPZMaMGfLhhx/K9LLpMnXaVJkyZYpMmjhRSkpKpLi4WAryC+T9
+        9/MkJydHxowZI1lZWTJy5EgZOmyoDBkyRFJTUyV5cLIMGjRIBgwYIH379pW4uDhBpv9qnd9POgMvKMjH
+        KdDPvLw8fOH7kpubK9nZ2TJ27Fj94tGjR+PLM2XUqCycURrEiOHDJSMjQ4YOtYNJk5SUFBmcMliSk5Ml
+        MTFRAxs4cKAG169/P4lDgH369JHY2FiJiYmR6OhoPS5XpISFucQRGq5/h6i743TDeQnnb/8VRX19vRQV
+        FSFb46QIGePPhYWFCsgAyXkGSGamATFixAgZDhDDMoZJenq6pFkZTUFWBw8miCQFoQASEiS+f3/p168f
+        shwnsRaI6OgYiYqKFicAHKp9T0IBgIBeeeWVvq+++mrUyy+/3NMC8XwMBMDgx48fL+PGjdOyFwJEPgCw
+        GqxETrYNwqqEBYBVUADDCMCjCqkpkuIBgFVIGJgg/ePj3QDsKhBAY/W74gyPRgUiJdThlMjISEHwRa+9
+        9tpogrAqQUo9+4cUYvATJkzQz2KA0CoUFEp+fr7kogoE4EmlzMxMGTkKFLIroABQgbQ05bTSCACSkpI6
+        KYQK9HdXoJNGUVGxEhkRI+HOaK1AWLhTXE6XdOvWbVr37t2LXn/99b4WnZ4PoG5THYIvlZLSUgXhrgJo
+        lJePCgAAe2EMeiFrdJZo8Mr/EZIxDPxH4OmgzvOCT7T4nwD+x7uzb5o0tk+scj06OlYrEO6MQvAuCUUf
+        hIeHE0AZAIwDgH6/C6C2tlZKJpbIRCqHXQX2AgHkMfixkgnlYLYNVexMI8toVGY5Gefpho3vHy/9+xnO
+        M2CbMnbz6mcsmxg9AM47IyJl6zIACXOCSmHeA9iwYYOUlk40AErsKkD+AIC0KSwqlP3798vevXtlz549
+        0tbWJp999pl8+umn0tzcLOyhTZtqVXpXrlgp1dXVsnTJEpXb2XNmy8yZM6Ws7O/ywQcf4HtKlaYEFRUd
+        JdGeKhRhKuAICxeHw+E9gPXr18vESZNUu/kFpBGbmvwvRi/wz6+//irff/+9fPvtt/L111/LjRv/lKtf
+        filXOq7IhQsX5MyZM3L8+HE50n5EDuzbpyBbd7TKtm3bpKG+Qerq6oTfs2rVKlm2bBlmylJQKE6ikPWo
+        qChVoQiPCgQHB3sPgJmbPHmyTAIIVsEAKNbBc/DgQfntt9/k4cOHAHBPAdy+fVu++uoruXr1qnR0dCiA
+        06dPK4DDR47IPlSrrW2X7Nixw12hWqtCK1askOqqKlmCCmWhl5xOozgEQQARrgjw3yUBAQHeA1izZs0z
+        AIqKirVpSZ3Hjx/Lox8fyYMHD+S7776Tb775Rm7cvCnXrl2TK1c65OLFi6YCJ45LOyqw/wABoAKtVgUa
+        SLFNsm7dOjfFKioqVX7DwsM06IhIc1wul4Ly9+/tPYDVq1d2BQCOsoE5efeBDo+fPJaffvpJq3D37l0F
+        cAsArl+/DgBX5NKlS3Lm7Bk5ceIEALTLgQMHZPfu3R4AGjoBYDVhj1RUVqgYsFkZMAOPiOgE4Ofn5z0A
+        lrULhQCAk5g7Cxv3yZMn8vPPP8vDHwDg3l25c4cAbimAL74AgIuX5OyZs24A+wGg7SkAdVqB9ditVimA
+        yspKyG4qpm4o5NMAcHkA6NWrly8AatwAqEZUCa4RWZi2BoCpwAOPCtxkBZRCV+TiJUOhrhXwpJBdAQKw
+        K1CpuxLVhprfBQAGWc8ePbwHsBzbJlWIDVwKGR033ihQ5qhMBfBv9sCjH+W+3QP/Qg/cuKE90AEVcvcA
+        mlh7QJu4DU3cKs1QofqG51CookIntCMkxACwq4BKhOO89+573gNgSRm8mQMlOom5A3FZo+7/8ssvoM8P
+        cu/e81Toslw4f96tQkcsFdq1y1OFtgiHJdVOVQirOSnE7dQRYipg94FWAuedd97xHkAVZI36rzOADQwJ
+        5RZqA3j06JHcv3/frUC3bpkGvnz5MrhvqMPA2bx7VP+NfPI0NTXpPWMjAKxZu0ZqamqE31eBCnAvCrEq
+        4AmAP7/11luCFcK7VaIC2WDmSyYw+2hgDC9uoNx3SCFbfe7cuYMhZs+Aa3IOmWfg+w+CMlbTkjr8Pzt3
+        7pTtLdtl69ZGqdu8WTbgkrQack26MvscZFypDYBOJSKVnC6nvPnmm94D4C8b77EDFRYW6BDj7kMKkToM
+        ngOM3L9+/RrU5wsdYCdOnrSk86AGzhVj+/bt0rS1SVo4hcn/p6Yws89Bxt2IACilVCKnzgAzB9544w3v
+        ASxZsljGg/fkPtfoAjRwdk62Dpq2XW1mfbiN9eEmg78uX2KF6LjcIWfPnpVjx47J4cOH3I1rD6/GxkYN
+        nldV8l+HmKVATNji8kUGQLAB4ITyRBCEnnAG7z2A8vJyXR3sm5jZQA0AUoHBc3Vg5k3wl1V5Tp061cn9
+        vXs6sw/ec8Ej9+s21+kdm9Pe8L9SlixeLIsWLdIbGXeeUFbAamR+hgMM1mjvASxauEgHF49eYMB/bqHD
+        sOtz42Tw17D3kDaXOxA8dP/cuXO6+3BX4rRmpbj7cHmzs2+21E1dljjSh8EvWLhA7wIhwUE6zMIIAIEz
+        eILwCQB/mbnQd3UPuPu3tLTo0sad5/PPP5eL4P05UIfZ59rA4HfvbpOd2HtayP0mOBwInLTZWLvRZB/y
+        WVOzQtWH3Of3zZs/XwEEBRGAw/QBAg/DKs39yCcA8/HL8qH75v7Lq2O27kHcVSiD3DhJmXPnz+nEPYnG
+        Zfbb24/KkUOHsX2a9VmVx2pg0ocbKNcHXaGXL4P60JYpV0tm7ty5pgJBITqNFQCDxyePTwD4C0mb3JxO
+        G4WuAwGQDuchl2ew6zDr1Hw2LrN/6JChz24rePuCYysPL0qd3Lezv1D9JJ5Y3MZYAQJgHzBwfoaG+giA
+        2WDT2mc0PCAOsSFpQ7QRT582w+o4Aj969ChU57Byf+/ezsxr8NuaAbhBNkP3bXOMysMLDLlvZ/8TmGEE
+        QE8o0AbAPkDgDJ494VMFZs+erU2b7WFgcYjxks6b1DGlS7teVhi4Xi8xH3bh0kLa2JlntbYgeFs2SR17
+        cFF57CvmrFmzLADogcAgnQWhrAIC56fDVwC0B+m82e4bXQcOsdSUVA3GzjhvWnv27HXfiVtbdyjnuTI0
+        NDRq5vnv10PzV8OWtNcG6v7ChQuV9wzeBsAeCAwKVAAOR6hSyT4+VWDmxx/LaOz+tEx4ByB9OANSU9Nk
+        w/oNyn1eUOzLPIcVs76tZZtOXHJ+M/Reg8e91w6+ugqXewRP2Zw3b76QOgyen9OnT9dBxjlgAFjBY7kL
+        cYT4RqEZM2aq18Nje54ZGcOVQmzkW7duaRVaQRc7eMorFUqDpykMvWfTrlu3BqbwKs2+uhMWgLkQClKV
+        3GfwY2HVUDYVAAImAALRA2XyqQIfffQPUIYuG71OZB/0ycAMoHPMS0cqbMKKJRVCuWX26EZPnzYdJsBk
+        vfwUYn5QxSi9pJ75fylqJdI+Yab1gDL8jIMbocGjgbtmPwSAQlSZfAJAazwjY6Q01zgkfSiCzxihbjON
+        Wpq0SYlJurvTnFI3GQ4CzVc6CXQUXBFmhzd7jJmkHEimKQ23mWXuPcx4cIhFG9BFqWNnHp9B+PvAwEDf
+        AJSVlYEqw+VEUw+pXxaKDA7H6XSa6XEmJhmHOX6Abc4ae/Bpt822ywks0rrjcj0gIIcjDMGGIeuhAIOD
+        z+BghzmgTWAQgg8IUkvFpwqQk2kI+vjWntLe0Evqqx3w99O1ialENGo9vf4EmLQD4gd0MWptMKSJp++v
+        fg/ATCoIlNK8ACnNx8kLlBL8XJJrzoRcf5mQw9NbAvwDAMJHANOmTcMLSboca+wph7f4KYgtVQ5JSuZj
+        BQAMJgDjNHv6nwkJxrD1dJyNadv5eEHPMwKWodNF6zwCtHKBTmxeJ+gSBrqEin+AQ/z8Q8Svd7D07h2g
+        IHyqwNSpU5HxIXKquSeq0EsrcbKpp2xdHgyL3NjkrMCzAFAJ9EYnAJq4sM3jDAB1ntEzUwqDZVJ+kB6t
+        gkcFNPOowHhkf1y2H6rgB1PLRwBTYLpSNZKSU8H1ND2DEvFzIriPo4GjB9jMXSuAFxcCeMo2j8NV0Vae
+        mBja5zHoB1TBaWzDULjP7Af2QBD4T+77+wdKb57egb4DoGvMOzElsYgrtfUqw/WC3hCl0f0GBkqxGoMG
+        JSp9+CDHYGOUKhG6kNFpoBT6+/uLHwyqHvB43n77bfueq/T4o+PTjcx6CexuvUkV4XMaTpnn4WPD/3ro
+        MvhyvH6hsQB041sU36T4rMOXkRfgePdGZr2avYSM9yAIvknxWecFON69UloA+A7L91i+y/J99kU5f/xO
+        /NS7pf06/iJ9ukP8D3GWhQo97UjxAAAAAElFTkSuQmCC
+</value>
+  </data>
+</root>
\ No newline at end of file
diff -r 77e062628ef5 -r 361e324a0ed4 GUI/HardwareNode.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI/HardwareNode.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,119 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using Aga.Controls.Tree;
+using OpenHardwareMonitor.Hardware;
+
+namespace OpenHardwareMonitor.GUI {
+  public class HardwareNode : Node {
+
+    private IHardware hardware;
+
+    private List<TypeNode> typeNodes = new List<TypeNode>();
+
+    public HardwareNode(IHardware hardware) : base(hardware.Name) {
+      
+      this.hardware = hardware;
+      this.Image = hardware.Icon;
+
+      typeNodes.Add(new TypeNode(SensorType.Voltage));
+      typeNodes.Add(new TypeNode(SensorType.Clock));
+      typeNodes.Add(new TypeNode(SensorType.Temperature));
+      typeNodes.Add(new TypeNode(SensorType.Fan));
+      
+      foreach (ISensor sensor in hardware.Sensors)
+        SensorAdded(sensor);
+
+      hardware.SensorAdded +=new SensorEventHandler(SensorAdded);
+      hardware.SensorRemoved += new SensorEventHandler(SensorRemoved);
+    }
+
+    public IHardware Hardware {
+      get { return hardware; }
+    }
+
+    public void SetVisible(SensorType sensorType, bool visible) {
+      foreach (TypeNode node in typeNodes)
+        if (node.SensorType == sensorType) {
+          node.IsVisible = visible;
+          UpdateNode(node);
+        }
+    }
+
+    private void UpdateNode(TypeNode node) {      
+      if (node.IsVisible && node.Nodes.Count > 0) {
+        if (!Nodes.Contains(node)) {
+          int i = 0;
+          while (i < Nodes.Count &&
+            ((TypeNode)Nodes[i]).SensorType < node.SensorType)
+            i++;
+          Nodes.Insert(i, node);  
+        }
+      } else {
+        if (Nodes.Contains(node))
+          Nodes.Remove(node);
+      }
+    }
+
+    private void SensorRemoved(ISensor sensor) {
+      foreach (TypeNode node in typeNodes)
+        if (node.SensorType == sensor.SensorType) {
+          node.Nodes.Remove(new SensorNode(sensor));
+          UpdateNode(node);
+        }
+    }
+
+    private void InsertSorted(Node node, ISensor sensor) {
+      int i = 0;
+      while (i < node.Nodes.Count &&
+        ((SensorNode)node.Nodes[i]).Sensor.Index < sensor.Index)
+        i++;
+      node.Nodes.Insert(i, new SensorNode(sensor));        
+    }
+
+    private void SensorAdded(ISensor sensor) {
+      foreach (TypeNode node in typeNodes)
+        if (node.SensorType == sensor.SensorType) {
+          InsertSorted(node, sensor);
+          UpdateNode(node);
+        }
+    }
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 GUI/LicenseBox.resources
Binary file GUI/LicenseBox.resources has changed
diff -r 77e062628ef5 -r 361e324a0ed4 GUI/MainForm.Designer.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI/MainForm.Designer.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,523 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+namespace OpenHardwareMonitor.GUI {
+  partial class MainForm {
+    /// <summary>
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary>
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Windows Form Designer generated code
+
+    /// <summary>
+    /// Required method for Designer support - do not modify
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.components = new System.ComponentModel.Container();
+      System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
+      this.treeView = new Aga.Controls.Tree.TreeViewAdv();
+      this.sensor = new Aga.Controls.Tree.TreeColumn();
+      this.value = new Aga.Controls.Tree.TreeColumn();
+      this.min = new Aga.Controls.Tree.TreeColumn();
+      this.max = new Aga.Controls.Tree.TreeColumn();
+      this.limit = new Aga.Controls.Tree.TreeColumn();
+      this.nodeImage = new Aga.Controls.Tree.NodeControls.NodeIcon();
+      this.nodeCheckBox = new Aga.Controls.Tree.NodeControls.NodeCheckBox();
+      this.nodeTextBoxText = new Aga.Controls.Tree.NodeControls.NodeTextBox();
+      this.nodeTextBoxValue = new Aga.Controls.Tree.NodeControls.NodeTextBox();
+      this.nodeTextBoxMin = new Aga.Controls.Tree.NodeControls.NodeTextBox();
+      this.nodeTextBoxMax = new Aga.Controls.Tree.NodeControls.NodeTextBox();
+      this.nodeTextBoxLimit = new Aga.Controls.Tree.NodeControls.NodeTextBox();
+      this.columnsContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
+      this.valueToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.minMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.maxMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.limitMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.menuStrip = new System.Windows.Forms.MenuStrip();
+      this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.saveReportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.viewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.sensorsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.voltMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.clocksMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.tempMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.fansMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
+      this.plotMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.hddMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.timer = new System.Windows.Forms.Timer(this.components);
+      this.splitContainer = new System.Windows.Forms.SplitContainer();
+      this.plotPanel = new OpenHardwareMonitor.GUI.PlotPanel();
+      this.columnsContextMenuStrip.SuspendLayout();
+      this.menuStrip.SuspendLayout();
+      this.splitContainer.Panel1.SuspendLayout();
+      this.splitContainer.Panel2.SuspendLayout();
+      this.splitContainer.SuspendLayout();
+      this.SuspendLayout();
+      // 
+      // treeView
+      // 
+      this.treeView.BackColor = System.Drawing.SystemColors.Window;
+      this.treeView.Columns.Add(this.sensor);
+      this.treeView.Columns.Add(this.value);
+      this.treeView.Columns.Add(this.min);
+      this.treeView.Columns.Add(this.max);
+      this.treeView.Columns.Add(this.limit);
+      this.treeView.DefaultToolTipProvider = null;
+      this.treeView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.treeView.DragDropMarkColor = System.Drawing.Color.Black;
+      this.treeView.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+      this.treeView.FullRowSelect = true;
+      this.treeView.GridLineStyle = Aga.Controls.Tree.GridLineStyle.Horizontal;
+      this.treeView.LineColor = System.Drawing.SystemColors.ControlDark;
+      this.treeView.Location = new System.Drawing.Point(0, 0);
+      this.treeView.Model = null;
+      this.treeView.Name = "treeView";
+      this.treeView.NodeControls.Add(this.nodeImage);
+      this.treeView.NodeControls.Add(this.nodeCheckBox);
+      this.treeView.NodeControls.Add(this.nodeTextBoxText);
+      this.treeView.NodeControls.Add(this.nodeTextBoxValue);
+      this.treeView.NodeControls.Add(this.nodeTextBoxMin);
+      this.treeView.NodeControls.Add(this.nodeTextBoxMax);
+      this.treeView.NodeControls.Add(this.nodeTextBoxLimit);
+      this.treeView.RowHeight = 18;
+      this.treeView.SelectedNode = null;
+      this.treeView.Size = new System.Drawing.Size(478, 567);
+      this.treeView.TabIndex = 0;
+      this.treeView.Text = "treeView";
+      this.treeView.UseColumns = true;
+      this.treeView.Click += new System.EventHandler(this.treeView_Click);
+      // 
+      // sensor
+      // 
+      this.sensor.Header = "Sensor";
+      this.sensor.SortOrder = System.Windows.Forms.SortOrder.None;
+      this.sensor.TooltipText = null;
+      this.sensor.Width = 250;
+      // 
+      // value
+      // 
+      this.value.Header = "Value";
+      this.value.SortOrder = System.Windows.Forms.SortOrder.None;
+      this.value.TooltipText = null;
+      this.value.Width = 100;
+      // 
+      // min
+      // 
+      this.min.Header = "Min";
+      this.min.SortOrder = System.Windows.Forms.SortOrder.None;
+      this.min.TooltipText = null;
+      this.min.Width = 100;
+      // 
+      // max
+      // 
+      this.max.Header = "Max";
+      this.max.SortOrder = System.Windows.Forms.SortOrder.None;
+      this.max.TooltipText = null;
+      this.max.Width = 100;
+      // 
+      // limit
+      // 
+      this.limit.Header = "Limit";
+      this.limit.SortOrder = System.Windows.Forms.SortOrder.None;
+      this.limit.TooltipText = null;
+      this.limit.Width = 100;
+      // 
+      // nodeImage
+      // 
+      this.nodeImage.DataPropertyName = "Image";
+      this.nodeImage.LeftMargin = 1;
+      this.nodeImage.ParentColumn = this.sensor;
+      this.nodeImage.ScaleMode = Aga.Controls.Tree.ImageScaleMode.Fit;
+      // 
+      // nodeCheckBox
+      // 
+      this.nodeCheckBox.DataPropertyName = "Plot";
+      this.nodeCheckBox.EditEnabled = true;
+      this.nodeCheckBox.LeftMargin = 3;
+      this.nodeCheckBox.ParentColumn = this.sensor;
+      // 
+      // nodeTextBoxText
+      // 
+      this.nodeTextBoxText.DataPropertyName = "Text";
+      this.nodeTextBoxText.EditEnabled = true;
+      this.nodeTextBoxText.IncrementalSearchEnabled = true;
+      this.nodeTextBoxText.LeftMargin = 3;
+      this.nodeTextBoxText.ParentColumn = this.sensor;
+      // 
+      // nodeTextBoxValue
+      // 
+      this.nodeTextBoxValue.DataPropertyName = "Value";
+      this.nodeTextBoxValue.IncrementalSearchEnabled = true;
+      this.nodeTextBoxValue.LeftMargin = 3;
+      this.nodeTextBoxValue.ParentColumn = this.value;
+      // 
+      // nodeTextBoxMin
+      // 
+      this.nodeTextBoxMin.DataPropertyName = "Min";
+      this.nodeTextBoxMin.IncrementalSearchEnabled = true;
+      this.nodeTextBoxMin.LeftMargin = 3;
+      this.nodeTextBoxMin.ParentColumn = this.min;
+      // 
+      // nodeTextBoxMax
+      // 
+      this.nodeTextBoxMax.DataPropertyName = "Max";
+      this.nodeTextBoxMax.IncrementalSearchEnabled = true;
+      this.nodeTextBoxMax.LeftMargin = 3;
+      this.nodeTextBoxMax.ParentColumn = this.max;
+      // 
+      // nodeTextBoxLimit
+      // 
+      this.nodeTextBoxLimit.DataPropertyName = "Limit";
+      this.nodeTextBoxLimit.EditEnabled = true;
+      this.nodeTextBoxLimit.IncrementalSearchEnabled = true;
+      this.nodeTextBoxLimit.LeftMargin = 3;
+      this.nodeTextBoxLimit.ParentColumn = this.limit;
+      // 
+      // columnsContextMenuStrip
+      // 
+      this.columnsContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.valueToolStripMenuItem,
+            this.minMenuItem,
+            this.maxMenuItem,
+            this.limitMenuItem});
+      this.columnsContextMenuStrip.Name = "columnsContextMenuStrip";
+      this.columnsContextMenuStrip.Size = new System.Drawing.Size(104, 92);
+      // 
+      // valueToolStripMenuItem
+      // 
+      this.valueToolStripMenuItem.Checked = true;
+      this.valueToolStripMenuItem.CheckOnClick = true;
+      this.valueToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
+      this.valueToolStripMenuItem.Name = "valueToolStripMenuItem";
+      this.valueToolStripMenuItem.Size = new System.Drawing.Size(103, 22);
+      this.valueToolStripMenuItem.Text = "Value";
+      this.valueToolStripMenuItem.CheckedChanged += new System.EventHandler(this.valueToolStripMenuItem_CheckedChanged);
+      // 
+      // minMenuItem
+      // 
+      this.minMenuItem.Checked = true;
+      this.minMenuItem.CheckOnClick = true;
+      this.minMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
+      this.minMenuItem.Name = "minMenuItem";
+      this.minMenuItem.Size = new System.Drawing.Size(103, 22);
+      this.minMenuItem.Text = "Min";
+      this.minMenuItem.CheckedChanged += new System.EventHandler(this.minToolStripMenuItem_CheckedChanged);
+      // 
+      // maxMenuItem
+      // 
+      this.maxMenuItem.Checked = true;
+      this.maxMenuItem.CheckOnClick = true;
+      this.maxMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
+      this.maxMenuItem.Name = "maxMenuItem";
+      this.maxMenuItem.Size = new System.Drawing.Size(103, 22);
+      this.maxMenuItem.Text = "Max";
+      this.maxMenuItem.CheckedChanged += new System.EventHandler(this.maxToolStripMenuItem_CheckedChanged);
+      // 
+      // limitMenuItem
+      // 
+      this.limitMenuItem.Checked = true;
+      this.limitMenuItem.CheckOnClick = true;
+      this.limitMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
+      this.limitMenuItem.Name = "limitMenuItem";
+      this.limitMenuItem.Size = new System.Drawing.Size(103, 22);
+      this.limitMenuItem.Text = "Limit";
+      this.limitMenuItem.CheckedChanged += new System.EventHandler(this.limitToolStripMenuItem_CheckedChanged);
+      // 
+      // menuStrip
+      // 
+      this.menuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.fileToolStripMenuItem,
+            this.viewToolStripMenuItem,
+            this.optionsToolStripMenuItem,
+            this.helpToolStripMenuItem});
+      this.menuStrip.Location = new System.Drawing.Point(0, 0);
+      this.menuStrip.Name = "menuStrip";
+      this.menuStrip.Padding = new System.Windows.Forms.Padding(7, 2, 0, 2);
+      this.menuStrip.Size = new System.Drawing.Size(478, 24);
+      this.menuStrip.TabIndex = 1;
+      this.menuStrip.Text = "menuStrip1";
+      // 
+      // fileToolStripMenuItem
+      // 
+      this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.saveReportToolStripMenuItem,
+            this.exitToolStripMenuItem});
+      this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
+      this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
+      this.fileToolStripMenuItem.Text = "File";
+      // 
+      // saveReportToolStripMenuItem
+      // 
+      this.saveReportToolStripMenuItem.Name = "saveReportToolStripMenuItem";
+      this.saveReportToolStripMenuItem.Size = new System.Drawing.Size(136, 22);
+      this.saveReportToolStripMenuItem.Text = "Save Report";
+      this.saveReportToolStripMenuItem.Click += new System.EventHandler(this.saveReportToolStripMenuItem_Click);
+      // 
+      // exitToolStripMenuItem
+      // 
+      this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
+      this.exitToolStripMenuItem.Size = new System.Drawing.Size(136, 22);
+      this.exitToolStripMenuItem.Text = "Exit";
+      this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
+      // 
+      // viewToolStripMenuItem
+      // 
+      this.viewToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.sensorsToolStripMenuItem,
+            this.toolStripMenuItem1,
+            this.plotMenuItem});
+      this.viewToolStripMenuItem.Name = "viewToolStripMenuItem";
+      this.viewToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
+      this.viewToolStripMenuItem.Text = "View";
+      // 
+      // sensorsToolStripMenuItem
+      // 
+      this.sensorsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.voltMenuItem,
+            this.clocksMenuItem,
+            this.tempMenuItem,
+            this.fansMenuItem});
+      this.sensorsToolStripMenuItem.Name = "sensorsToolStripMenuItem";
+      this.sensorsToolStripMenuItem.Size = new System.Drawing.Size(114, 22);
+      this.sensorsToolStripMenuItem.Text = "Sensors";
+      // 
+      // voltMenuItem
+      // 
+      this.voltMenuItem.Checked = true;
+      this.voltMenuItem.CheckOnClick = true;
+      this.voltMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
+      this.voltMenuItem.Name = "voltMenuItem";
+      this.voltMenuItem.Size = new System.Drawing.Size(147, 22);
+      this.voltMenuItem.Text = "Voltages";
+      this.voltMenuItem.CheckedChanged += new System.EventHandler(this.UpdateSensorTypeChecked);
+      // 
+      // clocksMenuItem
+      // 
+      this.clocksMenuItem.Checked = true;
+      this.clocksMenuItem.CheckOnClick = true;
+      this.clocksMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
+      this.clocksMenuItem.Name = "clocksMenuItem";
+      this.clocksMenuItem.Size = new System.Drawing.Size(147, 22);
+      this.clocksMenuItem.Text = "Clocks";
+      this.clocksMenuItem.CheckedChanged += new System.EventHandler(this.UpdateSensorTypeChecked);
+      // 
+      // tempMenuItem
+      // 
+      this.tempMenuItem.Checked = true;
+      this.tempMenuItem.CheckOnClick = true;
+      this.tempMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
+      this.tempMenuItem.Name = "tempMenuItem";
+      this.tempMenuItem.Size = new System.Drawing.Size(147, 22);
+      this.tempMenuItem.Text = "Temperatures";
+      this.tempMenuItem.CheckedChanged += new System.EventHandler(this.UpdateSensorTypeChecked);
+      // 
+      // fansMenuItem
+      // 
+      this.fansMenuItem.Checked = true;
+      this.fansMenuItem.CheckOnClick = true;
+      this.fansMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
+      this.fansMenuItem.Name = "fansMenuItem";
+      this.fansMenuItem.Size = new System.Drawing.Size(147, 22);
+      this.fansMenuItem.Text = "Fans";
+      this.fansMenuItem.CheckedChanged += new System.EventHandler(this.UpdateSensorTypeChecked);
+      // 
+      // toolStripMenuItem1
+      // 
+      this.toolStripMenuItem1.Name = "toolStripMenuItem1";
+      this.toolStripMenuItem1.Size = new System.Drawing.Size(111, 6);
+      // 
+      // plotMenuItem
+      // 
+      this.plotMenuItem.Checked = true;
+      this.plotMenuItem.CheckOnClick = true;
+      this.plotMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
+      this.plotMenuItem.Name = "plotMenuItem";
+      this.plotMenuItem.Size = new System.Drawing.Size(114, 22);
+      this.plotMenuItem.Text = "Plot";
+      this.plotMenuItem.CheckedChanged += new System.EventHandler(this.plotToolStripMenuItem_CheckedChanged);
+      // 
+      // optionsToolStripMenuItem
+      // 
+      this.optionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.hddMenuItem});
+      this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem";
+      this.optionsToolStripMenuItem.Size = new System.Drawing.Size(61, 20);
+      this.optionsToolStripMenuItem.Text = "Options";
+      // 
+      // hddMenuItem
+      // 
+      this.hddMenuItem.CheckOnClick = true;
+      this.hddMenuItem.Name = "hddMenuItem";
+      this.hddMenuItem.Size = new System.Drawing.Size(141, 22);
+      this.hddMenuItem.Text = "HDD sensors";
+      this.hddMenuItem.CheckedChanged += new System.EventHandler(this.hddsensorsToolStripMenuItem_CheckedChanged);
+      // 
+      // helpToolStripMenuItem
+      // 
+      this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.aboutToolStripMenuItem});
+      this.helpToolStripMenuItem.Name = "helpToolStripMenuItem";
+      this.helpToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
+      this.helpToolStripMenuItem.Text = "Help";
+      // 
+      // aboutToolStripMenuItem
+      // 
+      this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
+      this.aboutToolStripMenuItem.Size = new System.Drawing.Size(107, 22);
+      this.aboutToolStripMenuItem.Text = "About";
+      this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click);
+      // 
+      // timer
+      // 
+      this.timer.Interval = 1000;
+      this.timer.Tick += new System.EventHandler(this.timer_Tick);
+      // 
+      // splitContainer
+      // 
+      this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.splitContainer.Location = new System.Drawing.Point(0, 24);
+      this.splitContainer.Name = "splitContainer";
+      this.splitContainer.Orientation = System.Windows.Forms.Orientation.Horizontal;
+      // 
+      // splitContainer.Panel1
+      // 
+      this.splitContainer.Panel1.Controls.Add(this.treeView);
+      // 
+      // splitContainer.Panel2
+      // 
+      this.splitContainer.Panel2.Controls.Add(this.plotPanel);
+      this.splitContainer.Panel2.Cursor = System.Windows.Forms.Cursors.Default;
+      this.splitContainer.Size = new System.Drawing.Size(478, 768);
+      this.splitContainer.SplitterDistance = 567;
+      this.splitContainer.SplitterWidth = 3;
+      this.splitContainer.TabIndex = 3;
+      // 
+      // plotPanel
+      // 
+      this.plotPanel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+      this.plotPanel.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.plotPanel.Font = new System.Drawing.Font("Segoe UI", 9F);
+      this.plotPanel.Location = new System.Drawing.Point(0, 0);
+      this.plotPanel.Name = "plotPanel";
+      this.plotPanel.Size = new System.Drawing.Size(478, 198);
+      this.plotPanel.TabIndex = 0;
+      // 
+      // MainForm
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.ClientSize = new System.Drawing.Size(478, 792);
+      this.Controls.Add(this.splitContainer);
+      this.Controls.Add(this.menuStrip);
+      this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+      this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+      this.MainMenuStrip = this.menuStrip;
+      this.Name = "MainForm";
+      this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
+      this.Text = "Open Hardware Monitor";
+      this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.MainForm_FormClosed);
+      this.columnsContextMenuStrip.ResumeLayout(false);
+      this.menuStrip.ResumeLayout(false);
+      this.menuStrip.PerformLayout();
+      this.splitContainer.Panel1.ResumeLayout(false);
+      this.splitContainer.Panel2.ResumeLayout(false);
+      this.splitContainer.ResumeLayout(false);
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+
+    #endregion
+
+    private Aga.Controls.Tree.TreeViewAdv treeView;
+    private System.Windows.Forms.MenuStrip menuStrip;
+    private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
+    private Aga.Controls.Tree.TreeColumn sensor;
+    private Aga.Controls.Tree.TreeColumn value;
+    private Aga.Controls.Tree.TreeColumn min;
+    private Aga.Controls.Tree.TreeColumn max;
+    private Aga.Controls.Tree.NodeControls.NodeIcon nodeImage;
+    private Aga.Controls.Tree.NodeControls.NodeTextBox nodeTextBoxText;
+    private Aga.Controls.Tree.NodeControls.NodeTextBox nodeTextBoxValue;
+    private Aga.Controls.Tree.NodeControls.NodeTextBox nodeTextBoxMin;
+    private Aga.Controls.Tree.NodeControls.NodeTextBox nodeTextBoxMax;
+    private System.Windows.Forms.Timer timer;
+    private System.Windows.Forms.SplitContainer splitContainer;
+    private PlotPanel plotPanel;
+    private System.Windows.Forms.ToolStripMenuItem viewToolStripMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem plotMenuItem;
+    private Aga.Controls.Tree.NodeControls.NodeCheckBox nodeCheckBox;
+    private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;
+    private Aga.Controls.Tree.TreeColumn limit;
+    private Aga.Controls.Tree.NodeControls.NodeTextBox nodeTextBoxLimit;
+    private System.Windows.Forms.ContextMenuStrip columnsContextMenuStrip;
+    private System.Windows.Forms.ToolStripMenuItem minMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem maxMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem limitMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem valueToolStripMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem saveReportToolStripMenuItem;
+    private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
+    private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem sensorsToolStripMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem clocksMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem tempMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem fansMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem voltMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem hddMenuItem;
+  }
+}
+
diff -r 77e062628ef5 -r 361e324a0ed4 GUI/MainForm.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI/MainForm.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,325 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Configuration;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using Aga.Controls.Tree;
+using Aga.Controls.Tree.NodeControls;
+using OpenHardwareMonitor.Hardware;
+
+namespace OpenHardwareMonitor.GUI {
+  public partial class MainForm : Form {
+
+    private Node root;
+    private List<IGroup> groupList = new List<IGroup>();
+    private TreeModel treeModel;
+    private IDictionary<ISensor, Color> sensorPlotColors = 
+      new Dictionary<ISensor, Color>();
+    private Color[] plotColorPalette;
+
+    public MainForm() {
+      
+      InitializeComponent();
+      this.Font = SystemFonts.MessageBoxFont;
+      treeView.Font = SystemFonts.MessageBoxFont;
+      plotPanel.Font = SystemFonts.MessageBoxFont;      
+      
+      nodeCheckBox.IsVisibleValueNeeded += 
+        new EventHandler<NodeControlValueEventArgs>(
+          nodeCheckBox_IsVisibleValueNeeded);
+      nodeCheckBox.CheckStateChanged += 
+        new EventHandler<TreePathEventArgs>(UpdatePlotSelection);
+      nodeTextBoxText.DrawText += 
+        new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
+      nodeTextBoxValue.DrawText +=
+        new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
+      nodeTextBoxMin.DrawText +=
+        new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
+      nodeTextBoxMax.DrawText +=
+        new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
+      nodeTextBoxLimit.DrawText += 
+        new EventHandler<DrawEventArgs>(nodeTextBoxLimit_DrawText);
+
+      if (Utilities.Config.Contains("mainForm.Location.X")) {
+        int x = Utilities.Config.Get("mainForm.Location.X", Location.X);
+        x = x < 0 ? 0 : x;
+        int y = Utilities.Config.Get("mainForm.Location.Y", Location.Y);
+        y = y < 0 ? 0 : y;
+        this.Location = new Point(x, y);
+      } else {
+        StartPosition = FormStartPosition.CenterScreen;
+      }
+
+      Width = Utilities.Config.Get("mainForm.Width", Width);
+      Height = Utilities.Config.Get("mainForm.Height", Height);
+         
+      treeModel = new TreeModel();
+      root = new Node(System.Environment.MachineName);
+      root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
+      
+      treeModel.Nodes.Add(root);
+      treeView.Model = treeModel;
+
+      AddGroup(new Hardware.SMBIOS.SMBIOSGroup());
+      AddGroup(new Hardware.LPC.LPCGroup());
+      AddGroup(new Hardware.CPU.CPUGroup());
+      AddGroup(new Hardware.ATI.ATIGroup());
+      AddGroup(new Hardware.Nvidia.NvidiaGroup());
+      AddGroup(new Hardware.TBalancer.TBalancerGroup());
+      
+      plotColorPalette = new Color[14];
+      plotColorPalette[0] = Color.Blue;
+      plotColorPalette[1] = Color.OrangeRed;
+      plotColorPalette[2] = Color.Green;
+      plotColorPalette[3] = Color.LightSeaGreen;
+      plotColorPalette[4] = Color.Goldenrod;
+      plotColorPalette[5] = Color.DarkViolet;
+      plotColorPalette[6] = Color.YellowGreen;
+      plotColorPalette[7] = Color.SaddleBrown;
+      plotColorPalette[8] = Color.Gray;
+      plotColorPalette[9] = Color.RoyalBlue;
+      plotColorPalette[10] = Color.DeepPink;
+      plotColorPalette[11] = Color.MediumSeaGreen;
+      plotColorPalette[12] = Color.Olive;
+      plotColorPalette[13] = Color.Firebrick;
+
+      plotMenuItem.Checked = Utilities.Config.Get(plotMenuItem.Name, false);
+      minMenuItem.Checked = Utilities.Config.Get(minMenuItem.Name, false);
+      maxMenuItem.Checked = Utilities.Config.Get(maxMenuItem.Name, true);
+      limitMenuItem.Checked = Utilities.Config.Get(limitMenuItem.Name, false);
+      hddMenuItem.Checked = Utilities.Config.Get(hddMenuItem.Name, false);
+
+      voltMenuItem.Checked = Utilities.Config.Get(voltMenuItem.Name, true);
+      clocksMenuItem.Checked = Utilities.Config.Get(clocksMenuItem.Name, true);
+      tempMenuItem.Checked = Utilities.Config.Get(tempMenuItem.Name, true);
+      fansMenuItem.Checked = Utilities.Config.Get(fansMenuItem.Name, true);
+
+      timer.Enabled = true;
+    }
+
+    private void AddGroup(IGroup group) {
+      groupList.Add(group);
+      foreach (IHardware hardware in group.Hardware)
+        root.Nodes.Add(new HardwareNode(hardware));
+    }
+
+    private void RemoveGroup(IGroup group) {
+      List<Node> nodesToRemove = new List<Node>();
+      foreach (IHardware hardware in group.Hardware)
+        foreach (Node node in root.Nodes) {
+          HardwareNode hardwareNode = node as HardwareNode;
+          if (hardwareNode != null && hardwareNode.Hardware == hardware)
+            nodesToRemove.Add(node);
+        }
+      foreach (Node node in nodesToRemove)
+        root.Nodes.Remove(node);
+      groupList.Remove(group);
+    }
+
+    private void nodeTextBoxLimit_DrawText(object sender, DrawEventArgs e) {
+      SensorNode sensorNode = e.Node.Tag as SensorNode;
+      if (sensorNode != null) 
+        e.Text = sensorNode.ValueToString(sensorNode.Sensor.Limit);
+    }
+
+    private void nodeTextBoxText_DrawText(object sender, DrawEventArgs e) {
+      if (!plotMenuItem.Checked)
+        return;      
+
+      SensorNode sensorNode = e.Node.Tag as SensorNode;
+      if (sensorNode != null) {
+        Color color;
+        if (sensorPlotColors.TryGetValue(sensorNode.Sensor, out color)) 
+          e.TextColor = color;        
+      }
+    }
+
+    private void UpdatePlotSelection(object sender, 
+      TreePathEventArgs e) 
+    {
+      List<ISensor> selected = new List<ISensor>();
+      IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
+      int colorIndex = 0;
+      foreach (TreeNodeAdv node in treeView.AllNodes) {
+        SensorNode sensorNode = node.Tag as SensorNode;
+        if (sensorNode != null && 
+          sensorNode.Sensor.SensorType == SensorType.Temperature) {
+          if (sensorNode.Plot) {
+            colors.Add(sensorNode.Sensor,
+              plotColorPalette[colorIndex % plotColorPalette.Length]);
+            selected.Add(sensorNode.Sensor);
+          }
+          colorIndex++;
+        }
+      }
+      sensorPlotColors = colors;
+      plotPanel.SetSensors(selected, colors);
+    }
+
+    private void nodeCheckBox_IsVisibleValueNeeded(object sender, 
+      NodeControlValueEventArgs e) {
+      SensorNode node = e.Node.Tag as SensorNode;
+      e.Value = (node != null) && 
+        (node.Sensor.SensorType == SensorType.Temperature) && 
+        plotMenuItem.Checked;
+    }
+
+    private void exitToolStripMenuItem_Click(object sender, EventArgs e) {
+      Close();
+    }
+
+    private void timer_Tick(object sender, EventArgs e) {
+      
+      #if !DEBUG
+      try {
+      #endif
+        foreach (IGroup group in groupList)
+          foreach (IHardware hardware in group.Hardware)
+            hardware.Update();
+      #if !DEBUG
+      } catch (Exception exception) {
+        Utilities.CrashReport.Save(exception);
+        Close();
+      }
+      #endif
+            
+      treeView.Invalidate();
+      plotPanel.Invalidate();
+    }
+
+    private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
+      Utilities.Config.Set(plotMenuItem.Name, plotMenuItem.Checked);
+      Utilities.Config.Set(minMenuItem.Name, minMenuItem.Checked);
+      Utilities.Config.Set(maxMenuItem.Name, maxMenuItem.Checked);
+      Utilities.Config.Set(limitMenuItem.Name, limitMenuItem.Checked);
+      Utilities.Config.Set(hddMenuItem.Name, hddMenuItem.Checked);
+
+      Utilities.Config.Set(voltMenuItem.Name, voltMenuItem.Checked);
+      Utilities.Config.Set(clocksMenuItem.Name, clocksMenuItem.Checked);
+      Utilities.Config.Set(tempMenuItem.Name, tempMenuItem.Checked);
+      Utilities.Config.Set(fansMenuItem.Name, fansMenuItem.Checked);
+
+      Utilities.Config.Set("mainForm.Location.X", Location.X);
+      Utilities.Config.Set("mainForm.Location.Y", Location.Y);
+      Utilities.Config.Set("mainForm.Width", Width);
+      Utilities.Config.Set("mainForm.Height", Height);
+
+      foreach (IGroup group in groupList)
+        group.Close();
+    }
+
+    private void aboutToolStripMenuItem_Click(object sender, EventArgs e) {
+      new AboutBox().ShowDialog();
+    }
+
+    private void plotToolStripMenuItem_CheckedChanged(object sender, 
+      EventArgs e) 
+    {
+      splitContainer.Panel2Collapsed = !plotMenuItem.Checked;
+      treeView.Invalidate();
+    }
+
+    private void valueToolStripMenuItem_CheckedChanged(object sender, 
+      EventArgs e) 
+    {
+      treeView.Columns[1].IsVisible = valueToolStripMenuItem.Checked;
+    }
+
+    private void minToolStripMenuItem_CheckedChanged(object sender, EventArgs e) 
+    {
+      treeView.Columns[2].IsVisible = minMenuItem.Checked;
+    }
+
+    private void maxToolStripMenuItem_CheckedChanged(object sender, EventArgs e) 
+    {
+      treeView.Columns[3].IsVisible = maxMenuItem.Checked;
+    }
+
+    private void limitToolStripMenuItem_CheckedChanged(object sender, 
+      EventArgs e) {
+      treeView.Columns[4].IsVisible = limitMenuItem.Checked;
+    }
+
+    private void treeView_Click(object sender, EventArgs e) {
+      
+      MouseEventArgs m = e as MouseEventArgs;
+      if (m == null || m.Button != MouseButtons.Right)
+        return;
+
+      NodeControlInfo info = treeView.GetNodeControlInfoAt(new Point(m.X, m.Y));
+      if (info.Control == null)
+        columnsContextMenuStrip.Show(treeView, m.X, m.Y);
+    }
+
+    private void saveReportToolStripMenuItem_Click(object sender, EventArgs e) {
+      ReportWriter.Save(groupList, new Version(Application.ProductVersion));
+    }
+
+    private void hddsensorsToolStripMenuItem_CheckedChanged(object sender, 
+      EventArgs e) 
+    {
+      if (hddMenuItem.Checked) {
+        AddGroup(new Hardware.HDD.HDDGroup());
+        UpdateSensorTypeChecked(null, null);
+      } else {
+        List<IGroup> groupsToRemove = new List<IGroup>();
+        foreach (IGroup group in groupList) 
+          if (group is Hardware.HDD.HDDGroup)
+            groupsToRemove.Add(group);
+        foreach (IGroup group in groupsToRemove) {
+          group.Close();
+          RemoveGroup(group);
+        }
+        UpdatePlotSelection(null, null);        
+      }
+    }
+
+    private void UpdateSensorTypeChecked(object sender, EventArgs e) {
+      foreach (HardwareNode node in root.Nodes) {
+        node.SetVisible(SensorType.Voltage, voltMenuItem.Checked);
+        node.SetVisible(SensorType.Clock, clocksMenuItem.Checked);
+        node.SetVisible(SensorType.Temperature, tempMenuItem.Checked);
+        node.SetVisible(SensorType.Fan, fansMenuItem.Checked);
+      }
+    }  
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 GUI/MainForm.resources
Binary file GUI/MainForm.resources has changed
diff -r 77e062628ef5 -r 361e324a0ed4 GUI/MainForm.resx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI/MainForm.resx	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,393 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="columnsContextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>204, 15</value>
+  </metadata>
+  <metadata name="menuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="timer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>124, 15</value>
+  </metadata>
+  <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>55</value>
+  </metadata>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAMAEBAAAAEACABoBQAANgAAACAgAAABACAAqBAAAJ4FAAAwMAAAAQAgAKglAABGFgAAKAAAABAA
+        AAAgAAAAAQAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMTFAAYGBkAFxkZABkZGQAXGhoAGhoaABkb
+        GwAbGxsAGxwcABwcHAAbHR0AHR0dAB0dHgAeHh4AIB4eAB0gIAAgICAAIiEhACMhIQAiIiIAJSMjAB4k
+        JAAjJCQAIiQlACYmJgAqJiYAJCcnACcnJwApJycAKCgoACcpKQAqKioAKysqACQrLQArKysAKSssAB4s
+        LgAfLC4AKS0sACwtLQAvLS0AIC4xADAtMAAxLi4ALy8vACswMAAxMTEAMDIzADQyMgAyMzMAMzMzADQ0
+        MgA0NDQANTU1ADU2NgA2NjYAOzc1ADg4OABAODcAOTk5ADo5OQA5OjoAKjs9ADo8PAA8PDwAPT09ACE/
+        QwAoQEMAPz8/ADtAPgBDPz8AQ0BAAEBBQQBBQUEAIkJJACVCSAAnQ0gAKENKAENDQgBEREQAJkVMAEVF
+        RQBFSEkASEhIACVJUgBDSUoATExLAExMTABNTUoATU1NAE5OTgBET1IAT09PAFJPTwBQUFAAUVFRAFJR
+        UgBSUlIAUVNTAFJTUwBTU1MAVFRUAFVVVQBMV1kAV1dXAFlXWQBRWFkAV1hYAFlZWQBdW1oAW1tbAFxc
+        XABeXl4AX19fAGFfXwBgX2AAYWJhAGJiYgBkZGUAZWRlAGVlZQBmZmYAaGhoAGlpaABpaWkAbGxrAGxs
+        bAAqb30AbW1tACtvfgBubm4Ab29vAHBwcABwcXEAd3d3AHd4eAB5eXkAenp6AHx8fAB+fn4AgICAAICB
+        gQCBgYEAg4SDAIaFhgCGh4YAh4eHAIeIiACLiYkAioqKAIuLiwCOjo4Aj4+PAJGRkQCSkpMAk5SUAJSU
+        lACVlZUAlpaWAJiYmACampoAnJycAJ6engCfn58AoKCgAKGhoQCioqIAC6fJAKGjpACkpKQApaWlAKWm
+        pACmpqYAqaepAKqoqgCpq6kAqquqAK2trQCsra8Ar62vAK6urACxsbEAsrKyALOzswC0tbQAtbW1ALa2
+        tgC3t7cAuri6ALy8vAC9vb0Avr++AL+/vwDBwcEAwsLCAMTExADFxcUAyMXIAMjIyADKysoAy8rLAMzM
+        zADQ0NAA0tLSANra2gDd3d0A4uHiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjW1VIQDk0LCIbFw8KBgQAZ6d/RTk1
+        MzAuK0xQS0pCAmqBOjg9MioiGxIVJCUpIQFrUkaNmZCLhoR6cm1HDhQDblNZpLaspp+Zk4yIbxAYBXBT
+        XKm5tKuinJWOiW8LGwd1V2KxwbqupJ2YkYxxCx0IeF1lu8e/s6igm5aPdAwiCXthaL7Lw7Wqo5+YkncN
+        Hw19ZmjDzMa9ta2hmZR5ECAQgmhpxc3IwLivopqWehMfEYNsb8nOysS8sqWel34cJhaEbGSuwrewpZ6W
+        jIdsGUMahWhfWmZeWFNOQTw3KC1NHoRfYVZTUUlBPzs1MSg+VCOKgHx2c29oYFlTT0Q7Ni8nAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgA
+        AAAgAAAAQAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAQcH
+        BwMGBgYEBgYGBAYGBgQGBgYEBgYGBAYGBgQGBgYEBgYGBAYGBgQGBgYEBgYGBAYGBgQGBgYEBgYGBAYG
+        BgQGBgYEBgYGBAYGBgQGBgYEBgYGBAYGBgQGBgYEBgYGBAcHBwMFBQUCAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAKCgoJDAwMIA0NDSoNDQ0qDQ0NKg0NDSoNDQ0qDQ0NKg0NDSoNDQ0qDQ0NKg0NDSoNDQ0qDQ0NKg0N
+        DSoNDQ0qDQ0NKg0NDSoNDQ0qDQ0NKg0NDSoNDQ0qDQ0NKg0NDSoNDQ0qDAwMJQoKChEFBQUCAAAAAAAA
+        AAAAAAAAAAAAAAgICBQKCgpHDAwMWwwMDFwMDAxcDAwMXAwMDFwMDQxcDQ0NXA0NDVwNDQ1cDQ0NXA0N
+        DVwNDQ1cDQ0OXA4ODlwODg5cDg4OXA4ODlwODg5cDg4OXA4ODlwODg5cDg4OXA4ODlsNDQ1SDAwMJQcH
+        BwMAAAAAAAAAAAAAAABhYWGPWVhYxVFQT9JKSUnYSEdH2EJCQtg9Pj7YOTk52Tg3NtkzMjPZLi4v2Ssr
+        K9kmJibZIyMj2SAgH9kbGxvZFxcY2RMTE9kPDg7ZDQwM2Q0MDNgNDAzYDQwM2A0NDdgNDQ3YDg0Nuw4O
+        DlsNDQ0qBgYGBAAAAAAAAAAAAAAAAGJhYb88QkP/NlJZ/zZSWf83T1T/PTw8/zw8PP86Ojr/OTk5/zg4
+        OP82Njb/NDQ0/zQ0NP8yMjL/MTEw/y8uMP8sNTj/KjY4/yc0Nf8mMjT/JDAy/yIuMP8fLC7/Hyst/x8i
+        Iv8NDQ3YDg4OXA0NDSoGBgYEAAAAAAAAAAAAAAAAY2NivzhUWv8al7L/G5Or/zNdZf8+PT3/PT09/zs7
+        O/86Ojn/Nzc4/zU2Nf80NDT/MzMz/zExMP8vLy//Li4u/ys0Nv8pNTb/JzI0/yYwM/8kLzH/Iy4w/yEs
+        Lv8fKy3/HyEi/w0NDdgODg5cDQ0NKgYGBgQAAAAAAAAAAAAAAABmZGS/Oldd/xqSrP8yZG7/QT8//z4/
+        Pv88PDz/OTk5/zY3Nv80NDX/MzIz/zIyMv8wMDD/Ly8v/y4uLv8tLCz/Kikp/yNIUP8iR1D/IUZP/yBG
+        Tv8gRk7/H0VN/x87Qf8gHx//DQ0N2A4ODlwNDQ0qBgYGBAAAAAAAAAAAAAAAAGlnaL8+Vlv/N2Fq/0ZD
+        Q/9BQED/PT09/zg3N/8yMjH/Li4u/ywsLP8rKyv/KSkp/yoqKv8oKCj/Jycn/yUlJf8lJCT/JCMj/yMh
+        If8jIiL/JCIi/yQjI/8kIyP/IiEh/yEgIP8NDQ3YDg4OXA0NDSoGBgYEAAAAAAAAAAAAAAAAampqv0lI
+        SP9IR0f/RkZG/0FBQf9GR0b/f3+A/4CAgP94eHj/cXFx/2tra/9kZGT/XV1e/1dXV/9PT0//SEhI/0ND
+        Qv9AQED/QEBA/zs7O/8mJib/IyMj/yQkJP8jIyP/IyMh/w0NDdgODg5cDQ0NKgYGBgQAAAAAAAAAAAAA
+        AABubm6/S0tL/0pKS/9ISEj/QUFB/4uLi/+srKz/oaKh/5+fnv+dm53/mJiY/5SUlP+QkI//i4uL/4WG
+        hf+AgID/e3t6/3V0df9xcXH/a2tr/zs7O/8hISL/JCQk/yQkJP8kJCP/DQ0N2A4ODlwNDQ0qBgYGBAAA
+        AAAAAAAAAAAAAHBwcL9NTU3/TE1N/0lKSv9AQD//lpaY/6urq/+op6f/pKSk/6ChoP+dnJz/mJiY/5OT
+        k/+Ojo7/iImI/4ODgv99fX3/d3d3/3Fxcf9xcXH/Pz8//yEhIf8kJCT/JSUl/yUkJP8NDQ3ZDg4OXA0N
+        DSoGBgYEAAAAAAAAAAAAAAAAcnJzv09OT/9OT0//TExM/0FBQf+bm5r/srKy/66urv+rq6v/p6en/6Ki
+        ov+dnZ3/mZmZ/5OTk/+Njo7/iIiH/4GBgf98e3z/dHV0/3Fxcf8/Pz//ISEh/yQkJf8lJSX/JSYm/w0N
+        DdkODg5cDQ0NKgYGBgQAAAAAAAAAAAAAAAB0dXW/UVFR/1BQUP9NTU3/QkJC/56env+4uLj/tLO0/7Gx
+        sf+tra3/qKio/6Ojo/+dnZ3/mJeX/5GSkf+MjIv/hYWF/35/f/94eHj/c3Nz/z8/P/8iIiL/JSUl/yYm
+        Jv8mJib/DQ0N2Q4ODlwNDQ0qBgYGBAAAAAAAAAAAAAAAAHZ2dr9UVFT/U1NT/09PT/9FRUX/pKSk/7+/
+        v/+7u7v/tra2/7Gxsf+pqan/o6Oj/52dnf+Xl5f/kJGR/46Njf+JiYn/goKC/3x8fP93d3f/QEBA/yIi
+        Iv8mJib/Jycn/ycnJ/8NDQ3ZDg4OXA0NDSoGBgYEAAAAAAAAAAAAAAAAeHh4v1dXVv9VVVX/UFBQ/0ZG
+        Rv+pqKn/xsbG/8HBwf+8vLz/tra2/6usrP+lpaX/n5+f/5mYmP+VlJX/kZKS/4yNjP+FhYX/f35//3p6
+        ev9BQUH/IiIj/yYmJv8oJyj/KCcn/w0NDdkODg5cDQ0NKgYGBgQAAAAAAAAAAAAAAAB6enq/WFlZ/1dX
+        V/9SUlP/SEhI/62trf/MzMz/xsbG/8HBwf+7u7v/sLCw/6mpqf+jo6P/nJ2d/5aWlv+Tk5P/j4+O/4iI
+        iP+AgYD/fHx9/0JCQv8jIyP/Jycn/ygoKP8oKCj/Dg4O2Q4ODlwNDQ0qBgYGBAAAAAAAAAAAAAAAAH18
+        fb9bW1v/WVlZ/1RVVf9ISUn/sbGx/9LS0v/Ly8v/xcXF/7+/vv+zs7P/qqqq/6SlpP+gn5//mpqa/5qY
+        mv+RkZH/i4uK/4KDg/9+fn7/QkND/yMkJP8nJyf/KSkp/ykpKf8QEBDZDg4OXA0NDSoGBgYEAAAAAAAA
+        AAAAAAAAfn5+v11dXf9bW1v/VlZW/0tJSf+zsrL/1tbW/8/Pz//Jycn/wsLC/7W1tf+ura3/p6en/6Ki
+        ov+cnJz/mZiZ/5OTk/+MjIz/hYWF/39/f/9GRUb/JCQk/ygoKP8pKSn/KSkp/xISEtkODg5cDQ0NKgYG
+        BgQAAAAAAAAAAAAAAACBgYG/Xl5e/1xcXP9XWFf/SkpK/7S0tP/a29r/0tLS/83MzP/FxcX/v7+//7i4
+        uP+xsbH/q6uq/6Ojo/+cnJz/lJWU/42Njf+GhYb/gICA/0lJSP8jIyP/KCgo/ykpKf8pKSn/FBQU2Q4O
+        DlwNDQ0qBgYGBAAAAAAAAAAAAAAAAIODg79fX1//Xl5e/1lYWf9LS0v/tLS0/93d3f/U1NT/zs7O/8fG
+        x//AwMD/ubm5/7Kysv+rq6v/pKSk/5ycnP+VlZb/jo6O/4eHh/+BgYH/TU1N/yMkJP8oKSj/Kikp/ykp
+        Kf8YGBjZDg4OXA0NDSoGBgYEAAAAAAAAAAAAAAAAhYWFv2BgX/9eXl7/WlpZ/01NTf+2trb/3t7e/9XV
+        1f/Oz8//x8fH/8HBwf+5ubr/srKz/6ysq/+kpKT/nZ2d/5WVlv+Ojo7/h4eH/4GBgf9QUFD/JCQk/ykp
+        Kf8pKSn/KCgo/xoZGdkODg5cDQ0NKgYGBgQAAAAAAAAAAAAAAACIhoa/YGBg/15eXv9aWlr/T09P/7e3
+        t//d3d3/1NTU/87Ozv/Hx8f/wMDA/7m5uf+ysrL/q6ur/6OjpP+cnJz/lZWV/46Ojf+Ghob/gYGB/1NT
+        U/8mJib/Kioq/yorKv8oKCn/Gxwc2A4ODlwNDQ0qBgYGBAAAAAAAAAAAAAAAAIqKir9fX1//Xl5e/1pb
+        Wv9RUVH/rKys/+Li4v/S0tL/zM3M/8XFxv+/v7//uLm4/7Kysf+rq6v/pKSk/52dnf+VlZX/jY6O/4eG
+        h/+BgYH/U1JS/ykpKf8sLCz/Ki8x/ycuL/8eHh7YDQ0NXA0NDSoGBgYEAAAAAAAAAAAAAAAAjIuMv15e
+        Xv9dXV3/Wlpa/1VVVf9cXFz/qqqq/7Gxsf+urq7/qqqq/6Sko/+dnZ3/lZWV/46Ojv+Hh4f/gH9//3d5
+        d/9wcHD/aWlp/1xcXP8zMzP/LCws/y0tLf8rMDH/Jy0u/yAgINgNDQ1cDQ0NKgYGBgQAAAAAAAAAAAAA
+        AACOjo6/XFxc/1xcXP9aWlr/VldX/1BRUP9MTEv/R0dH/0RERP9AQUD/Pj4+/zw8PP86Ozr/ODg4/zg4
+        OP81NTX/MzMz/zExMf8wMDD/Li4v/y4uLv8uLS//Kj1A/yg5Pv8lODv/IyIi2A0NDVwNDQ0qBgYGBAAA
+        AAAAAAAAAAAAAJGRkb9aW1v/W1ta/1hZWP9WVlb/VFRU/1BQUP9OTk7/TExM/0pJSv9HR0f/RUVF/0JC
+        Qv9AQED/Pj4+/zw8PP86Ojr/Nzg3/zU1Nf8yMjL/MTEx/y8uLv8pOz//KDtA/yU6QP8lJCTYDQ0NWw0N
+        DSoHBwcEAAAAAAAAAAAAAAAAk5OTv1hYWP9ZWVn/WFdY/1VVVf9SUlL/UFBQ/05OTv9NTE3/SkpK/0hI
+        SP9GRkb/Q0JD/0BBQP8/Pz//PT09/zs7Ov84ODj/NjU1/zMzM/8xMTH/Ly4t/yFbZ/8qLzH/Jy4v/ygo
+        KNIMDAxHDAwMIAcHBwMAAAAAAAAAAAAAAACSk5K/VVRV/1RVVf9UVFT/UlFR/09PT/9NTU7/TEtM/0pK
+        Sv9ISUj/R0dH/0RFRP9BQUH/Pz8//z4+Pv87Ozz/OTo5/zc3N/80NDT/MTEx/y8wMP8uLi7/LSws/ykv
+        MP8lLS7/LS0txQoKChQKCgoJAwMDAQAAAAAAAAAAAAAAAJeWl4+SkpK/kJCQv42Li7+Hh4e/hISEv4CA
+        gL98fHy/d3d3v3R0dL9wcHC/bGpsv2ZmZr9jY2O/X19fv1tbW79VVVW/UlJSv05OTr9KSkq/REREv0FB
+        Qb89PT2/OTk5vzMzM78xMTGPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////
+        ////////4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AA
+        AAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAf/////////////
+        //8oAAAAMAAAAGAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAA
+        AAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAA
+        AAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAggICAcJCQkMCAgIDgcHBw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcH
+        Bw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcH
+        Bw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOBwcHDgcHBw4HBwcOBwcHDggICA4JCQkMCAgIBwAA
+        AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAgIBwsLCxkNDQ0sDQ0NMg0NDTMNDQ0zDQ0NMw0N
+        DTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0N
+        DTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0NDTMNDQ0zDQ0NMw0N
+        DTINDQ0sCwsLGggICAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCQkJDA0NDSwNDQ1MDg4OVw4O
+        DlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4O
+        DlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4ODlkODg5ZDg4OWQ4O
+        DlkODg5ZDg4OWQ4ODlcNDQ1MDQ0NLAkJCQwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBQUFDgoK
+        CjILCwtXCwsLZAsLC2YLCwtmCwsLZgsLC2YMDAxmDAwMZgwMDGYMDAxmDAwMZgwMDGYMDAxmDAwMZgwM
+        DGYNDQ1mDQ0NZg0NDWYNDQ1mDQ0NZg0NDWYNDQ1mDQ0NZg4ODmYODg5mDg4OZg4ODmYODg5mDg4OZg4O
+        DmYODg5mDg4OZg4ODmYODg5mDg4OZg4ODmQODg5XDQ0NMggICA4AAAABAAAAAAAAAAAAAAAAAAAAAAAA
+        AABiYmL/XFxc/1paWv9VVVf/U1NS/1FRUf9OTk7/S0pL/0dHR/9DQ0P/QUFB/z8+P/88PDz/Ojk5/zU1
+        Nf8yMjL/MDAw/y0tLv8qKir/JiYm/yQjJP8hISH/Hh4e/xsbHP8ZGRn/FBQU/xEREf8PDw//Dg4O/w4O
+        Dv8ODg7/Dg4O/w4ODv8ODg7/Dg4O/w4ODv8ODg7/Dw8P/w4ODmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAA
+        AAAAAAAAAAAAAAAAAABiYmH/Pjw8/z88O/9AOzr/QDs6/z86Of89Ojr/PTo6/zs7O/86Ozr/Ozo7/zo6
+        Ov85OTn/ODg4/zc3N/82NjX/NTU0/zMzM/8yMjL/MTEx/zEyMf8wMDD/MDAw/y8uLv8uLS3/LCor/yoo
+        KP8pJyf/KCYl/yYkJP8lIyP/JCIh/yIhIP8gHh7/IB4d/yAdHf8fHh7/Dg4O/w4ODmYODg5ZDQ0NMwcH
+        Bw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAABjY2P/QT49/xqYs/8blrD/Gpaw/xqXsv8igpb/Pj09/z09
+        Pf88PDz/Ozs7/zo6Ov85OTn/ODg4/zc3N/82Njb/NDQ0/zMzM/8zMjL/MjEx/zAxMP8vLy//Ly8v/y4u
+        Lf8iVmH/IVRf/yFUX/8fU13/IFNd/x9TXP8fUVz/HlBb/x5RW/8dUFr/HE9Z/xxQW/8fHh7/Dg4O/w4O
+        DmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAABkZGT/Qj08/xqVr/8ckqv/G5St/yR/
+        kv9APDv/Pz4+/z49Pv89PDz/Ozs7/zo6Ov85OTn/ODg4/zY3N/81NTX/NDQ0/zMzM/8yMjL/MTEx/zAw
+        L/8vLy//Li4u/y0tLP8sKir/LSko/yomJv8pJSX/JyQj/ygiIv8mIiH/JSAg/yQfHv8jHhz/Ih0c/x8d
+        Hf8fHh//Dg4O/w4ODmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAABlZWX/RkFA/xqW
+        sP8blK3/JICT/0I+Pf9APz//Pz4//z4+Pv88PDz/Ojo6/zk5Of83Nzf/NjU2/zQ0NP8zMzP/MjIy/zEx
+        Mf8wMDD/Ly8w/y8vL/8uLi7/LS0t/ywsLP8rKyr/IFVf/x9TXf8fVF3/IFNd/x9TXP8fUVz/H1Fc/x5R
+        W/8eUFv/HVBb/x8eH/8fHyD/Dg4O/w4ODmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAA
+        AABmZmb/RkJC/xmXsf8lgZP/RkFB/0JBQf9BQUD/Pz8//z09Pf86Ozr/ODg4/zU2Nf8zMzP/MjIy/zEx
+        Mf8wMDD/Ly8v/y8vL/8uLi7/Li4u/y0tLf8rKyv/Kior/ykpKf8oJyf/JyYm/yYkJP8mIyT/JSMj/yUi
+        I/8lIyP/JCIi/yQiIv8jISL/IiEg/yEfIP8fHx//Dg4O/w4ODmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAA
+        AAAAAAAAAAAAAAAAAABoaGj/SEVF/ySDmP9HQ0L/R0VF/0NDQ/9BQUD/Pz8+/zs6O/82Njb/MTEx/y4u
+        Lv8sLC3/LS0t/ywsLP8rKyv/KSop/ykpKf8oKCj/KCgo/ycnJ/8nJib/JSUl/yUkJf8kJCT/IyQj/yMi
+        I/8iIiL/IiMi/yMjI/8kIyT/JCQk/yMjJP8jIyP/IyMj/yIiIf8gICD/Dg4O/w4ODmYODg5ZDQ0NMwcH
+        Bw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAABpamr/SEdH/0lHR/9JR0f/R0dG/0RERf9BQUH/PDw8/z4/
+        P/99e33/dXV1/3BwcP9ra2v/ZWRl/2BfX/9aWlr/VVVW/1FRUf9MTEz/R0dH/0FBQf8+PDz/Nzg3/zMz
+        M/8wMDD/MDAw/y8vMP8wMDD/MTAx/ycnJ/8hISL/IyMj/yQkJP8kJCT/IyMk/yMiIv8hISH/Dg4O/w4O
+        DmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAABta2v/SkpK/0pKSv9JSUn/SEhI/0ZF
+        Rf9AQED/QkJC/8nJyf+rq6v/n5+e/56env+cnJz/mpqa/5eXl/+UlJT/kpKR/4+Pj/+MjIz/iIqK/4aH
+        hv+Dg4P/gICA/3x8fP94eHj/dHRz/3Fxcf9ycnL/ZWVl/05PTv8nJyf/IiIi/yMkI/8kJCT/IyMj/yMj
+        I/8jISP/Dg4O/w4ODmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAABubm3/S0tM/0tM
+        S/9LS0v/SUlJ/0ZGRv9APz//jIuM/7Ozs/+jo6P/oqKi/6CgoP+enp7/nJyc/5mamf+Xlpf/lJSU/5CR
+        kf+Ojo7/i4uL/4eHh/+Dg4P/gH+A/3x8fP94eHj/dXR0/3BwcP9vb2//cHBw/2VlZf8wMDD/IiIi/yMj
+        I/8kJCT/JCQk/yQjJP8jJCP/Dg4O/w4ODmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAA
+        AABwcG//TU1N/01NTf9MTEz/SkpK/0dHR/8/Pj//jo6O/6urq/+pqan/p6em/6WkpP+ioqL/oKCg/52e
+        nv+bm5v/mJiY/5WUlP+RkZH/jo6O/4qKi/+Hh4f/g4OD/39/f/98fHz/d3d3/3Nzc/9vb2//b29v/3Jy
+        cv8vLy//ICEg/yMjI/8lJCT/JCQk/yQkJP8kJCT/Dg4O/w4ODmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAA
+        AAAAAAAAAAAAAAAAAABxcXH/Tk5O/05OT/9NTU3/TExM/0hISP9AQED/kJCQ/7Cwr/+tra3/rKyr/6mp
+        qf+np6f/pKSl/6Giof+fn5//nJyc/5iYmP+VlZX/kZGS/46Ojv+Kior/hoaG/4KCgv9+fn7/enp7/3Z2
+        dv9xcnH/b29v/3Jycv8vLi7/ISAh/yMjI/8kJCX/JSUl/yQkJf8lJST/Dg4O/w4ODmYODg5ZDQ0NMwcH
+        Bw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAABzc3P/T09P/09PT/9PT0//TU1M/0lJSf9BQEH/kpKS/7W0
+        tP+xsbH/r6+w/66urv+rq6v/qamp/6alpf+ioqL/n5+f/5ycnP+YmZj/lJWV/5GRkf+NjY3/iYmJ/4WF
+        hf+BgYH/fX19/3l5ef90dHT/cHBw/3Jycv8uLi7/ISEg/yQkJP8lJSX/JiUm/yYlJf8lJSX/Dg4O/w4O
+        DmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAB0dHT/UVFR/1FQUf9PT0//Tk5O/0tK
+        Sv9CQkL/lZWV/7i4uP+2tbX/s7Oz/7Gxsf+vr6//ra2t/6mqqv+mpqb/oqKj/5+fn/+cnJz/mJiY/5SU
+        lP+QkI//jIyM/4iIiP+Dg4P/f39//3t7e/93d3b/cnJy/3Jycv8uLy//ISEh/yQkJP8mJiX/JiYm/yYm
+        Jf8mJSX/Dg4O/w4ODmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAB1dXX/U1NU/1NT
+        U/9QUVH/T05O/0xMTP9CQkL/l5eX/76+vv+6urr/t7i3/7W1tf+ysrL/sLCw/66trf+rqqz/pqem/6Ki
+        ov+fn5//m5ub/5eWl/+SkpL/jo+O/4uKiv+Ghob/gYKB/31+fv95eXn/dHR0/3Nzc/8vLy//IyEj/yQk
+        JP8mJib/JyYn/yYmJv8mJib/Dg4O/w4ODmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAA
+        AAB2d3b/VVVV/1VVVf9TUlL/UFBQ/01NTf9ERET/mpqa/8LCwv++v7//vLy8/7m5uv+2trf/s7Oz/62t
+        rf+mpqb/oqOj/56en/+bm5r/lpeX/5OTkv+Ojo7/jY6N/42Njf+JiYj/hIOD/39/f/97e3v/dnd2/3V1
+        dP8vLy//ISEh/yQlJf8mJib/Jycn/ycmJv8mJyb/Dg4O/w4ODmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAA
+        AAAAAAAAAAAAAAAAAAB4d3j/VlZW/1ZWVv9UVFT/UVFR/05OTv9FRET/nJyc/8bGxv/CwsP/wMDA/72+
+        vf+6u7r/t7e3/7CwsP+pqan/pqam/6Khov+dnZ3/mZmZ/5WVlf+UlJT/k5OT/4+Pj/+Li4v/hoaG/4GB
+        gf99fX3/eHh4/3Z3dv8vLy//ISIj/yUlJf8nJyb/KCco/ygnJ/8nJyf/Dg4O/w4ODmYODg5ZDQ0NMwcH
+        Bw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAB5eXn/WFhY/1dXV/9WVlb/UlNT/09PT/9GRkb/n5+f/8rL
+        yv/Gxsb/w8TE/8HBwf+9vb7/urq6/7Ozs/+srKz/qKio/6SlpP+goKD/m5ub/5eXl/+Tk5P/kpKS/5CR
+        kP+NjY3/iIiI/4ODg/9+f3//enp7/3h4eP8wMC//IiIi/yYmJf8nJyf/KCgo/ycnJ/8oJyf/Dg4O/w4O
+        DmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAB6e3v/WVla/1lZWf9XV1f/VFRV/09Q
+        T/9GRkb/oqGi/8/Pz//Ky8r/x8jH/8TExP/BwcH/vr2+/7a2tv+vr6//qqur/6enp/+ioqL/np6e/5mZ
+        mf+VlZX/lJSU/5OSkv+Ojo7/ioqK/4WFhf+AgID/fHx8/3h5ev8wMDD/IyIj/yYmJv8oJyj/KCgq/ygo
+        KP8nKCj/Dw8P/w4ODmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAB8fHz/W1ta/1pa
+        Wv9YWFj/VVZW/1BQUP9HR0f/pKSk/9LS0v/Ozs7/y8vL/8fHx//DxMT/wMDA/7m5uf+ysrH/ra2t/6mo
+        qP+lpaX/oKCg/5ubm/+Xlpf/mZma/5SUlP+QkI//i4uL/4aGhv+BgYH/fX19/3t7e/8wMDD/IyMj/yYm
+        Jv8oKCf/KSko/ykoKP8oKCj/EBAQ/w4ODmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAA
+        AAB+fn3/XFxc/1xbXP9aWVn/V1dW/1FRUf9ISEj/paWl/9bW1v/R0dH/zs7O/8vKyv/Gxsb/w8LC/7i4
+        t/+srKz/p6mn/6Ojov+enp7/oqKi/6Wlpf+fn5//m5qb/5WWlv+RkZD/jY2M/4iIh/+CgoL/fn5+/3x8
+        fP8xMjL/IyMj/yYnJ/8oKCj/KSkp/ygoKf8oKSj/ERER/w4ODmYODg5ZDQ0NMwcHBw4AAAABAAAAAAAA
+        AAAAAAAAAAAAAAAAAAB/f3//XV1d/11dXf9aWlv/WFhX/1JSUv9JSUn/pKSk/9ra2v/U1NT/0NDQ/83N
+        zf/Iycn/xMTE/729vf+1tbb/sbGx/6ysrP+oqKj/oqKk/52dnv+YmJj/mJiY/5eXl/+SkpL/jo6N/4iJ
+        iP+Dg4P/f39//319ff80NDT/IyMj/ycnJ/8oKCj/KSkp/ykpKf8oKCj/ExMT/w4ODmYODg5ZDQ0NMwcH
+        Bw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAACAgID/Xl5e/15eXv9cXFz/WVlZ/1NTU/9JSUn/pKSk/93d
+        3f/X19b/0tLS/8/Pz//Ly8v/xsbG/8LCwv+9vr7/uLi5/7S0tP+wsLD/rKys/6enpv+hoaH/nZ2d/5iY
+        mP+Sk5P/jo6O/4mJif+EhIT/f4CA/35+fv82Njb/JCMk/ycnJ/8oKCj/KSkp/ykpKf8pKSn/FhYW/w0N
+        DWYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAACCgoL/X19e/15eXv9dXF3/WVpZ/1RU
+        VP9KSUr/paWl/+Hh4P/Z2tr/1dXU/9DQ0P/NzM3/x8fH/8PDw/+/vr7/urq6/7W1tf+wsLD/rK2t/6en
+        p/+ioqL/np2d/5mZmP+UlJP/j4+P/4qKiv+FhYX/gICA/319ff85OTn/IyMk/ycnJ/8oKCn/KSkp/ykp
+        Kf8pKSf/GBcY/w0NDWYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAACDhIT/YGBg/19f
+        X/9eXV3/Wlpa/1VVVf9LSkv/paWl/+Hi4v/b29v/1tbV/9HR0f/Nzc3/yMjI/8PDxP+/v7//uru6/7W1
+        tf+xsbH/ra2t/6ioqP+io6P/np6e/5mZmf+UlJT/j4+P/4uKiv+FhYX/gICA/35+ff88PDz/JCQk/ycn
+        J/8pKSn/Kiop/ykpKf8oJyj/GRka/w0NDWYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAA
+        AACEhIT/YGBg/19fX/9eXl7/Wlpb/1ZWVv9LS0v/paWl/+Li4v/c3Nz/1tfW/9HS0f/Nzs7/ycjJ/8TE
+        xP+/wMD/u7q7/7a1tv+xsbH/ra2t/6iop/+jo6L/np6e/5mZmf+UlJT/j4+Q/4uKiv+GhYX/gICA/35+
+        fv8/QED/JSUl/ygoJ/8pKSn/Kiop/ykpKf8oKCj/Gxsb/w0NDWYODg5ZDQ0NMwcHBw4AAAABAAAAAAAA
+        AAAAAAAAAAAAAAAAAACFh4f/YGBg/19fX/9eXl7/Wlpb/1ZWV/9MTEz/pqam/+Hi4f/b29v/1tbW/9HR
+        0f/Nzc3/yMjJ/8TExP+/v7//u7u7/7W2tf+xsbH/ra2t/6ioqP+jo6P/np6e/5mZmf+UlJT/j4+P/4qK
+        iv+FhYX/gICA/31+ff9CQkL/JiYm/ygoKP8pKSn/Kioq/ykpKf8oKCj/HBwc/w0NDWYODg5ZDQ0NMwcH
+        Bw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAACIiIj/YGBg/19fX/9eXl7/W1tb/1hXV/9OTk3/p6en/+Hh
+        4f/a2dr/1dXV/9DQ0P/Nzc3/yMjH/8PDw/++v7//urq6/7W1tf+wsbD/rK2t/6eop/+ioqL/np6e/5mZ
+        mf+TlJT/j4+P/4qKiv+FhIX/gICA/359ff9GRkb/Jicm/yopKv8qKyr/Kisq/ykpKf8oKCj/HR4e/w0N
+        DWYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAACJiYn/YGBg/19fX/9eXl7/W1tb/1hY
+        WP9QUFD/qamp/+jo6P/W1tb/0tPT/8/Pz//Ly8v/xsbG/8LCwv++vr7/ubm5/7S0tP+wsLD/rKyr/6en
+        pv+hoqL/nZ2d/5iYmP+Tk5P/jo+O/4mJif+EhIT/f3+A/3t7e/9KSkv/KCgo/ysrK/8sLCz/Kyoq/yop
+        Kv8pJyf/Hx8f/w0NDWYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAACLi4v/X19e/15e
+        X/9dXV3/W1tb/1lYWP9UVFT/V1dY///////j4+P/09PT/8/Pz//Kysr/xcfH/8HBwv+/vr//ubm5/7W1
+        tf+wsLD/rK2s/6amqP+ioqL/np2e/5mZmf+Uk5T/kJCQ/4uLi/+Ghob/gYGB/3x8fP8xMC//Kyos/yws
+        LP8tLCz/Kyoq/xeBlv8oJif/IiIi/w0NDWYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAA
+        AACMjIz/Xl1d/15eXv9dXFz/W1tb/1hZWf9WVlX/Tk5O/1ZXVv+np6f/paWl/6SkpP+ioqL/oKCg/5yc
+        nP+YmJj/k5OT/46Pj/+JiYn/hYSF/4CAgP97e3z/dnZ2/3Fycf9tbW3/Z2Zm/2JiYv9dXV3/Wlpa/zMz
+        M/8sLSz/Li4t/y0tLf8tLS3/LCop/yknJv8nJiT/JCQk/w0NDWYODg5ZDQ0NMwcHBw4AAAABAAAAAAAA
+        AAAAAAAAAAAAAAAAAACOjo7/XF5c/15eXv9bW1z/Wlpa/1hYWP9WVlf/UlNT/05PT/9LS0r/R0dH/0RE
+        RP9CQkL/QEBA/z4/P/88PD3/Ozs7/zs7PP86Ojr/OTk5/zg4OP82Njb/NTQ1/zQzNP8zMzP/MTEx/zAw
+        MP8vLy//Ly8v/y4uLv8vLy//Li8u/y4tLf8tLSz/Kyoo/xeBlv8oJif/JiYm/w0NDWYODg5ZDQ0NMwcH
+        Bw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAACQj5D/XVtb/11dXP9bW1v/WVlZ/1hYWP9WVlb/U1RT/1JS
+        Uf9PT0//Tk5N/0tMS/9KSkr/SEhI/0dGR/9FREX/QkJD/0FBQv9AQED/Pz8//z4+Pv89PT3/Ozs7/zk5
+        Ov84ODj/NjY3/zU1Nf8zMzP/MjIy/zExMf8vMC//Ly8v/y8tLf8XgJX/LCgn/yknJv8pJiX/Jycn/w0N
+        DWYODg5ZDQ0NMwcHBw4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAACSkpL/Wlpa/1tbW/9aWlr/WVlY/1dX
+        V/9WVVb/VFRU/1JSUf9QT1D/Tk5O/01NTf9MTEz/SkpK/0hJSP9HR0f/RkZG/0RERP9CQkL/QEBA/z8/
+        P/8+Pj7/PT09/zs7O/85OTn/ODg4/zc3Nv80NDT/MzMz/zIyMv8wMDD/Ly8v/y8sLP8uKiv/LSgn/xiO
+        qv8oJyb/KSgp/w0NDWQODg5XDQ0NMggICA4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAACTk5P/WVhY/1pa
+        Wv9ZWVn/WFhY/1dXVv9VVVT/U1NT/1FRUf9QT1D/T09P/01OTv9MTEz/S0pL/0lJSf9ISEj/RkZG/0RE
+        RP9DQkL/QUFB/0A/P/8+Pz7/PT0+/zs8PP86Ojr/OTk5/zc4N/81NTT/MzMz/zEyMv8wMDD/Ly8v/y4t
+        Lf8XgJX/LSco/ysmJv8oJCX/Kysr/w0NDVcNDQ1MDQ0NLAkJCQwAAAABAAAAAAAAAAAAAAAAAAAAAAAA
+        AACTk5P/V1dX/1lYWP9YWFf/V1dX/1ZWVv9VVVX/UlJS/1BRUf9PT0//Tk5O/01NTf9MTEz/S0pK/0lJ
+        Sf9HR0f/RkZG/0RFRP9CQkL/QUFA/z8/P/8/Pz7/PT09/zs8PP86Ojr/ODg4/zc3Nv80NDX/MzMz/zEy
+        Mv8wMC//Ly8v/y4tLf8tLCz/Kyko/xiOqv8nJSX/LS0t/wwMDDINDQ0sCwsLGggICAcAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACSkpL/VFVV/1VVVf9UVVX/U1NT/1JSUv9RUVH/T09P/05OTv9NTU3/TExM/0pL
+        S/9LSUn/SUlJ/0hISP9GRkf/RUVF/0NDQ/9BQUH/QD8//z4+Pv89Pj3/PDw8/zo6Ov85OTn/ODg4/zY2
+        Nv8zNDP/MjIx/zAwMP8vLy//Li4u/y0tLf8tLS3/Kykp/ykmJv8nJST/Ly8v/wcHBw4JCQkMCAgIBwAA
+        AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACWlZX/k5KS/5KSkv+PkI//jY2N/4mJif+Hh4b/hYWF/4KC
+        g/9/gH//fXx8/3p5ef92dnb/dHR0/3Jycv9wcG//a2tr/2hoaP9lZmX/Y2Rj/2FhYf9eXl//XFxc/1hY
+        WP9VVFX/U1JS/1BQUP9NTU3/S0tL/0hISP9DREP/QUFB/z8/P/88PTz/OTk5/zY2Nv8yMjL/MTEx/wAA
+        AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAA////////AAD///////8AAP///////wAA////////AAD///////8AAPgA
+        AAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgA
+        AAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgA
+        AAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+        AAD///////8AAP///////wAA////////AAD///////8AAP///////wAA
+</value>
+  </data>
+</root>
\ No newline at end of file
diff -r 77e062628ef5 -r 361e324a0ed4 GUI/PlotPanel.Designer.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI/PlotPanel.Designer.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,79 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+namespace OpenHardwareMonitor.GUI {
+  partial class PlotPanel {
+    /// <summary> 
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.IContainer components = null;
+
+    /// <summary> 
+    /// Clean up any resources being used.
+    /// </summary>
+    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+    protected override void Dispose(bool disposing) {
+      if (disposing && (components != null)) {
+        components.Dispose();
+      }
+      base.Dispose(disposing);
+    }
+
+    #region Component Designer generated code
+
+    /// <summary> 
+    /// Required method for Designer support - do not modify 
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent() {
+      this.SuspendLayout();
+      // 
+      // PlotPanel
+      // 
+      this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
+      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+      this.Font = new System.Drawing.Font("Segoe UI", 9F);
+      this.Name = "PlotPanel";
+      this.Size = new System.Drawing.Size(170, 168);
+      this.ResumeLayout(false);
+
+    }
+
+    #endregion
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 GUI/PlotPanel.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI/PlotPanel.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,258 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Windows.Forms;
+using OpenHardwareMonitor.Hardware;
+
+namespace OpenHardwareMonitor.GUI {
+  public partial class PlotPanel : UserControl {
+
+    private DateTime now;
+    private List<ISensor> clocks = new List<ISensor>();
+    private List<ISensor> temperatures = new List<ISensor>();
+    private List<ISensor> fans = new List<ISensor>();
+    private IDictionary<ISensor, Color> colors;
+
+    private StringFormat centerlower;
+    private StringFormat centerleft;
+    private StringFormat lowerleft;
+    private Brush lightBrush;
+    private Pen lightPen;
+
+    public PlotPanel() {
+      this.SetStyle(ControlStyles.DoubleBuffer |
+        ControlStyles.UserPaint |
+        ControlStyles.AllPaintingInWmPaint | 
+        ControlStyles.ResizeRedraw, true);
+      this.UpdateStyles();
+
+      InitializeComponent();
+
+      centerlower = new StringFormat();
+      centerlower.Alignment = StringAlignment.Center;
+      centerlower.LineAlignment = StringAlignment.Near;
+
+      centerleft = new StringFormat();
+      centerleft.Alignment = StringAlignment.Far;
+      centerleft.LineAlignment = StringAlignment.Center;
+
+      lowerleft = new StringFormat();
+      lowerleft.Alignment = StringAlignment.Far;
+      lowerleft.LineAlignment = StringAlignment.Near;
+
+      lightBrush = new SolidBrush(Color.FromArgb(245, 245, 245));
+      lightPen = new Pen(Color.FromArgb(200, 200, 200));
+    }
+
+    private List<float> GetTemperatureGrid() {
+
+      float? minTempNullable = null;
+      float? maxTempNullable = null;
+      foreach (ISensor sensor in temperatures) {
+        IEnumerable<ISensorEntry> graph = sensor.Plot;
+        foreach (ISensorEntry entry in graph) {
+          if (!minTempNullable.HasValue || minTempNullable > entry.Value)
+            minTempNullable = entry.Value;
+          if (!maxTempNullable.HasValue || maxTempNullable < entry.Value)
+            maxTempNullable = entry.Value;
+        }
+      }
+      if (!minTempNullable.HasValue) {
+        minTempNullable = 20;
+        maxTempNullable = 30;
+      }
+
+      float maxTemp = (float)Math.Ceiling(maxTempNullable.Value / 10) * 10;
+      float minTemp = (float)Math.Floor(minTempNullable.Value / 10) * 10;
+      if (maxTemp == minTemp) 
+        maxTemp += 10;   
+     
+      int countTempMax = 4;
+      float deltaTemp = maxTemp - minTemp;
+      int countTemp = (int)Math.Round(deltaTemp / 2);
+      if (countTemp > countTempMax)
+        countTemp = (int)Math.Round(deltaTemp / 5);
+      if (countTemp > countTempMax)
+        countTemp = (int)Math.Round(deltaTemp / 10);
+      if (countTemp > countTempMax)
+        countTemp = (int)Math.Round(deltaTemp / 20);
+
+      List<float> grid = new List<float>(countTemp + 1);
+      for (int i = 0; i <= countTemp; i++) {
+        grid.Add(minTemp + i * deltaTemp / countTemp);
+      }
+      return grid;
+    }
+
+    private List<float> GetTimeGrid() {
+
+      float maxTime = 5;      
+      if (temperatures.Count > 0) {
+        IEnumerator<ISensorEntry> enumerator = 
+          temperatures[0].Plot.GetEnumerator();
+        if (enumerator.MoveNext()) {
+          maxTime = (float)(now - enumerator.Current.Time).TotalMinutes;
+        }
+      }
+
+      int countTime = 10;
+      float deltaTime = 5;
+      while (deltaTime + 1 < maxTime && deltaTime < 10)
+        deltaTime += 1;
+      while (deltaTime + 2 < maxTime && deltaTime < 30)
+        deltaTime += 2;
+      while (deltaTime + 5 < maxTime && deltaTime < 100)
+        deltaTime += 5;
+
+      List<float> grid = new List<float>(countTime + 1);
+      for (int i = 0; i <= countTime; i++) {
+        grid.Add(i * deltaTime / countTime);
+      }
+      return grid;
+    }
+
+    protected override void OnPaint(PaintEventArgs e) {
+
+      now = DateTime.Now - new TimeSpan(0, 0, 4);
+
+      List<float> timeGrid = GetTimeGrid();
+      List<float> tempGrid = GetTemperatureGrid();
+
+      Graphics g = e.Graphics;
+
+      RectangleF r =
+        new RectangleF(0, 0, Bounds.Width, Bounds.Height);
+
+      float ml = 40;
+      float mr = 15;
+      float x0 = r.X + ml;
+      float w = r.Width - ml - mr;
+
+      float mt = 15;
+      float mb = 28;
+      float y0 = r.Y + mt;
+      float h = r.Height - mt - mb;
+
+      float leftScaleSpace = 5;
+      float bottomScaleSpace = 5;
+      
+      g.Clear(Color.White);
+
+      if (w > 0 && h > 0) {
+        g.FillRectangle(lightBrush, x0, y0, w, h);
+
+        g.SmoothingMode = SmoothingMode.HighQuality;
+        for (int i = 0; i < timeGrid.Count; i++) {
+          float x = x0 + i * w / (timeGrid.Count - 1);
+          g.DrawLine(lightPen, x, y0, x, y0 + h);
+        }
+
+        for (int i = 0; i < tempGrid.Count; i++) {
+          float y = y0 + i * h / (tempGrid.Count - 1);
+          g.DrawLine(lightPen, x0, y, x0 + w, y);
+        }
+
+        float deltaTemp = tempGrid[tempGrid.Count - 1] - tempGrid[0];
+        float deltaTime = timeGrid[timeGrid.Count - 1];
+        foreach (ISensor sensor in temperatures) {
+          using (Pen pen = new Pen(colors[sensor])) {
+            IEnumerable<ISensorEntry> graph = sensor.Plot;
+            PointF last = new PointF();
+            bool first = true;
+            foreach (ISensorEntry entry in graph) {
+              PointF point = new PointF(
+                  x0 + w - w * (float)(now - entry.Time).TotalMinutes / deltaTime,
+                  y0 + h - h * (entry.Value - tempGrid[0]) / deltaTemp);
+              if (!first)
+                g.DrawLine(pen, last, point);
+              last = point;
+              first = false;
+            }
+          }
+        }
+
+        g.SmoothingMode = SmoothingMode.None;
+        g.FillRectangle(Brushes.White, 0, 0, x0, r.Height);
+        g.FillRectangle(Brushes.White, x0 + w + 1, 0, r.Width - x0 - w, 
+          r.Height);
+
+        for (int i = 1; i < timeGrid.Count; i++) {
+          float x = x0 + (timeGrid.Count - 1 - i) * w / (timeGrid.Count - 1);  
+          g.DrawString(timeGrid[i].ToString(), Font, Brushes.Black, x, 
+            y0 + h + bottomScaleSpace, centerlower);
+        }
+
+        for (int i = 0; i < tempGrid.Count - 1; i++) {
+          float y = y0 + (tempGrid.Count - 1 - i) * h / (tempGrid.Count - 1);
+          g.DrawString(tempGrid[i].ToString(), Font, Brushes.Black, 
+            x0 - leftScaleSpace, y, centerleft);
+        }
+
+        g.SmoothingMode = SmoothingMode.HighQuality;
+        g.DrawString("[°C]", Font, Brushes.Black, x0 - leftScaleSpace, y0,
+          lowerleft);        
+        g.DrawString("[min]", Font, Brushes.Black, x0 + w,
+          y0 + h + bottomScaleSpace, lowerleft);        
+      }
+    }
+
+    public void SetSensors(List<ISensor> sensors, 
+      IDictionary<ISensor, Color> colors) 
+    {
+      this.colors = colors;
+      List<ISensor> clocks = new List<ISensor>();
+      List<ISensor> temperatures = new List<ISensor>();
+      List<ISensor> fans = new List<ISensor>();
+      foreach (ISensor sensor in sensors)
+        switch (sensor.SensorType) {
+          case SensorType.Clock: clocks.Add(sensor); break;
+          case SensorType.Temperature: temperatures.Add(sensor); break;
+          case SensorType.Fan: fans.Add(sensor); break;
+        }
+      this.clocks = clocks;
+      this.temperatures = temperatures;
+      this.fans = fans;
+      Invalidate();
+    }
+
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 GUI/PlotPanel.resources
Binary file GUI/PlotPanel.resources has changed
diff -r 77e062628ef5 -r 361e324a0ed4 GUI/PlotPanel.resx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI/PlotPanel.resx	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff -r 77e062628ef5 -r 361e324a0ed4 GUI/SensorNode.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI/SensorNode.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,121 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using Aga.Controls.Tree;
+using OpenHardwareMonitor.Hardware;
+
+namespace OpenHardwareMonitor.GUI {
+  public class SensorNode : Node {
+    
+    private ISensor sensor;
+    private string format;
+    private bool plot = false;
+
+    public string ValueToString(float? value) {
+      if (value.HasValue)
+        return string.Format(format, value);
+      else
+        return "-";
+    }
+
+    public SensorNode(ISensor sensor) {
+      this.sensor = sensor;
+      switch (sensor.SensorType) {
+        case SensorType.Voltage: format = "{0:F2} V"; break;
+        case SensorType.Clock: format = "{0:F0} MHz"; break;
+        case SensorType.Temperature: format = "{0:F1} °C"; break;
+        case SensorType.Fan: format = "{0:F0} RPM"; break;
+      }      
+    }
+
+    public override string Text {
+      get { return sensor.Name; }
+      set { sensor.Name = value; }
+    }    
+
+    public bool Plot {
+      get { return plot; }
+      set { plot = value; }
+    }
+
+    public ISensor Sensor {
+      get { return sensor; }
+    }
+
+    public string Value {
+      get { return ValueToString(sensor.Value); }
+    }
+
+    public string Min {
+      get { return ValueToString(sensor.Min); }
+    }
+
+    public string Max {
+      get { return ValueToString(sensor.Max); }
+    }
+
+    public String Limit {
+      get {
+        return sensor.Limit.ToString();
+      }
+      set {
+        if (value != "")
+          sensor.Limit = float.Parse(value);
+        else
+          sensor.Limit = null;
+      }
+    }
+
+    public override bool Equals(System.Object obj) {
+      if (obj == null) 
+        return false;
+
+      SensorNode s = obj as SensorNode;
+      if (s == null) 
+        return false;
+
+      return (sensor == s.sensor);
+    }
+
+    public override int GetHashCode() {
+      return sensor.GetHashCode();
+    }
+
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 GUI/TypeNode.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI/TypeNode.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,82 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using Aga.Controls.Tree;
+using OpenHardwareMonitor.Hardware;
+
+namespace OpenHardwareMonitor.GUI {
+  public class TypeNode : Node {
+
+    private SensorType sensorType;
+    private bool visible = true;
+
+    public TypeNode(SensorType sensorType) : base() {
+      this.sensorType = sensorType;
+
+      switch (sensorType) {
+        case SensorType.Voltage: 
+          this.Image = Utilities.EmbeddedResources.GetImage("voltage.png");
+          this.Text = "Voltages";
+          break;
+        case SensorType.Clock:
+          this.Image = Utilities.EmbeddedResources.GetImage("clock.png");
+          this.Text = "Clocks";
+          break;
+        case SensorType.Temperature:
+          this.Image = Utilities.EmbeddedResources.GetImage("temperature.png");
+          this.Text = "Temperatures";
+          break;
+        case SensorType.Fan:
+          this.Image = Utilities.EmbeddedResources.GetImage("fan.png");
+          this.Text = "Fans";
+          break;
+      }
+    }
+
+    public SensorType SensorType {
+      get { return sensorType; }
+    }
+
+    public bool IsVisible {      
+      get { return visible; }
+      set { visible = value; }
+    }
+
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/ATI/ADL.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/ATI/ADL.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,251 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace OpenHardwareMonitor.Hardware.ATI {
+  
+  [StructLayout(LayoutKind.Sequential)]
+  public struct ADLAdapterInfo {
+    public int Size;
+    public int AdapterIndex;
+    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
+    public string UDID;
+    public int BusNumber;
+    public int DriverNumber;
+    public int FunctionNumber;
+    public int VendorID;
+    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
+    public string AdapterName;
+    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
+    public string DisplayName;
+    public int Present;
+    public int Exist;
+    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
+    public string DriverPath;
+    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
+    public string DriverPathExt;
+    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL.ADL_MAX_PATH)]
+    public string PNPString;
+    public int OSDisplayIndex;
+  }
+
+  [StructLayout(LayoutKind.Sequential)]
+  public struct ADLPMActivity {
+    public int Size;
+    public int EngineClock;
+    public int MemoryClock;
+    public int Vddc;
+    public int ActivityPercent;
+    public int CurrentPerformanceLevel;
+    public int CurrentBusSpeed;
+    public int CurrentBusLanes;
+    public int MaximumBusLanes;
+    public int Reserved;
+  }
+
+  [StructLayout(LayoutKind.Sequential)]
+  public struct ADLTemperature {
+    public int Size;
+    public int Temperature;
+  }
+
+  [StructLayout(LayoutKind.Sequential)]
+  public struct ADLFanSpeedValue {
+    public int Size;
+    public int SpeedType;
+    public int FanSpeed;
+    public int Flags;
+  }
+
+  [StructLayout(LayoutKind.Sequential)]
+  public struct ADLFanSpeedInfo {
+    public int Size;
+    public int Flags;
+    public int MinPercent;
+    public int MaxPercent;
+    public int MinRPM;
+    public int MaxRPM;
+  }
+
+  public class ADL {
+    public const int ADL_MAX_PATH = 256;
+    public const int ADL_MAX_ADAPTERS = 40;
+    public const int ADL_MAX_DISPLAYS = 40;
+    public const int ADL_MAX_DEVICENAME = 32;
+    public const int ADL_SUCCESS = 0;
+    public const int ADL_FAIL = -1;
+    public const int ADL_DRIVER_OK = 0;
+    public const int ADL_MAX_GLSYNC_PORTS = 8;
+    public const int ADL_MAX_GLSYNC_PORT_LEDS = 8;
+    public const int ADL_MAX_NUM_DISPLAYMODES = 1024;
+
+    public const int ADL_DL_FANCTRL_SPEED_TYPE_PERCENT = 1;
+    public const int ADL_DL_FANCTRL_SPEED_TYPE_RPM = 2;
+
+    public const int ADL_DL_FANCTRL_SUPPORTS_PERCENT_READ = 1;
+    public const int ADL_DL_FANCTRL_SUPPORTS_PERCENT_WRITE = 2;
+    public const int ADL_DL_FANCTRL_SUPPORTS_RPM_READ = 4;
+    public const int ADL_DL_FANCTRL_SUPPORTS_RPM_WRITE = 8;
+
+    private delegate int ADL_Main_Control_CreateDelegate(
+      ADL_Main_Memory_AllocDelegate callback, int enumConnectedAdapters);
+    private delegate int ADL_Adapter_AdapterInfo_GetDelegate(IntPtr info,
+      int size);
+
+    public delegate int ADL_Main_Control_DestroyDelegate();
+    public delegate int ADL_Adapter_NumberOfAdapters_GetDelegate(
+      ref int numAdapters);    
+    public delegate int ADL_Adapter_ID_GetDelegate(int adapterIndex,
+      out int adapterID);
+    public delegate int ADL_Adapter_Active_GetDelegate(int adapterIndex,
+      out int status);
+    public delegate int ADL_Overdrive5_CurrentActivity_GetDelegate(
+      int iAdapterIndex, ref ADLPMActivity activity);
+    public delegate int ADL_Overdrive5_Temperature_GetDelegate(int adapterIndex,
+        int thermalControllerIndex, ref ADLTemperature temperature);
+    public delegate int ADL_Overdrive5_FanSpeed_GetDelegate(int adapterIndex,
+        int thermalControllerIndex, ref	ADLFanSpeedValue fanSpeedValue);
+    public delegate int ADL_Overdrive5_FanSpeedInfo_GetDelegate(
+      int adapterIndex, int thermalControllerIndex,
+      ref ADLFanSpeedInfo fanSpeedInfo);
+
+    private static ADL_Main_Control_CreateDelegate
+      _ADL_Main_Control_Create;
+    private static ADL_Adapter_AdapterInfo_GetDelegate
+      _ADL_Adapter_AdapterInfo_Get;
+
+    public static ADL_Main_Control_DestroyDelegate
+      ADL_Main_Control_Destroy;
+    public static ADL_Adapter_NumberOfAdapters_GetDelegate
+      ADL_Adapter_NumberOfAdapters_Get;
+    public static ADL_Adapter_ID_GetDelegate
+      ADL_Adapter_ID_Get;
+    public static ADL_Adapter_Active_GetDelegate
+      ADL_Adapter_Active_Get;
+    public static ADL_Overdrive5_CurrentActivity_GetDelegate
+      ADL_Overdrive5_CurrentActivity_Get;
+    public static ADL_Overdrive5_Temperature_GetDelegate
+      ADL_Overdrive5_Temperature_Get;
+    public static ADL_Overdrive5_FanSpeed_GetDelegate
+      ADL_Overdrive5_FanSpeed_Get;
+    public static ADL_Overdrive5_FanSpeedInfo_GetDelegate
+      ADL_Overdrive5_FanSpeedInfo_Get;
+
+    private static string GetDllName() {
+      int p = (int)System.Environment.OSVersion.Platform;
+      if ((p == 4) || (p == 128)) {
+        if (IntPtr.Size == 4) {
+          return "atiadlxy.so";
+        } else {
+          return "atiadlxx.so";
+        }
+      } else {
+        if (IntPtr.Size == 4) {
+          return "atiadlxy.dll";
+        } else {
+          return "atiadlxx.dll";
+        }
+      }
+    }
+
+    private static void GetDelegate<T>(string entryPoint, out T newDelegate)
+      where T : class 
+    {
+      DllImportAttribute attribute = new DllImportAttribute(GetDllName());
+      attribute.CallingConvention = CallingConvention.StdCall;
+      attribute.PreserveSig = true;
+      attribute.EntryPoint = entryPoint;
+      PInvokeDelegateFactory.CreateDelegate(attribute, out newDelegate);
+    }
+
+    static ADL() {
+       GetDelegate("ADL_Main_Control_Create", 
+         out _ADL_Main_Control_Create);
+       GetDelegate("ADL_Adapter_AdapterInfo_Get", 
+         out _ADL_Adapter_AdapterInfo_Get);
+       GetDelegate("ADL_Main_Control_Destroy", 
+         out ADL_Main_Control_Destroy);
+       GetDelegate("ADL_Adapter_NumberOfAdapters_Get", 
+         out ADL_Adapter_NumberOfAdapters_Get);
+       GetDelegate("ADL_Adapter_ID_Get", 
+         out ADL_Adapter_ID_Get);
+       GetDelegate("ADL_Adapter_Active_Get", 
+         out ADL_Adapter_Active_Get);
+       GetDelegate("ADL_Overdrive5_CurrentActivity_Get", 
+         out ADL_Overdrive5_CurrentActivity_Get);
+       GetDelegate("ADL_Overdrive5_Temperature_Get", 
+         out ADL_Overdrive5_Temperature_Get);
+       GetDelegate("ADL_Overdrive5_FanSpeed_Get", 
+         out ADL_Overdrive5_FanSpeed_Get);
+       GetDelegate("ADL_Overdrive5_FanSpeedInfo_Get",
+          out ADL_Overdrive5_FanSpeedInfo_Get);
+    }
+
+    private ADL() { }
+
+    public static int ADL_Main_Control_Create(int enumConnectedAdapters) {
+      return _ADL_Main_Control_Create(Main_Memory_Alloc, enumConnectedAdapters);
+    }
+
+    public static int ADL_Adapter_AdapterInfo_Get(ADLAdapterInfo[] info) {
+      int elementSize = Marshal.SizeOf(typeof(ADLAdapterInfo));
+      int size = info.Length * elementSize;
+      IntPtr ptr = Marshal.AllocHGlobal(size);
+      int result = _ADL_Adapter_AdapterInfo_Get(ptr, size);
+      for (int i = 0; i < info.Length; i++)
+        info[i] = (ADLAdapterInfo)
+          Marshal.PtrToStructure((IntPtr)((long)ptr + i * elementSize),
+          typeof(ADLAdapterInfo));
+      Marshal.FreeHGlobal(ptr);
+      return result;
+    }
+
+    private delegate IntPtr ADL_Main_Memory_AllocDelegate(int size);
+
+    private static IntPtr Main_Memory_Alloc(int size) {
+      return Marshal.AllocHGlobal(size);;
+    }
+
+    private static void Main_Memory_Free(IntPtr buffer) {
+      if (IntPtr.Zero != buffer)
+        Marshal.FreeHGlobal(buffer);
+    }
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/ATI/ATIGPU.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/ATI/ATIGPU.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,117 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Reflection;
+
+namespace OpenHardwareMonitor.Hardware.ATI {
+  public class ATIGPU : IHardware {
+
+    private string name;
+    private Image icon;
+    private int adapterIndex;
+    private Sensor temperature;
+    private Sensor fan;
+    private Sensor coreClock;
+    private Sensor memoryClock;
+    private Sensor coreVoltage;
+
+    public ATIGPU(string name, int adapterIndex) {
+      this.name = name;
+      this.icon = Utilities.EmbeddedResources.GetImage("ati.png");
+      this.adapterIndex = adapterIndex;
+
+      ADLFanSpeedInfo speedInfo = new ADLFanSpeedInfo();
+      ADL.ADL_Overdrive5_FanSpeedInfo_Get(adapterIndex, 0, ref speedInfo);
+
+      this.temperature = 
+        new Sensor("GPU Core", 0, SensorType.Temperature, this);
+      this.fan = new Sensor("GPU", 0, speedInfo.MaxRPM, SensorType.Fan, this);
+      this.coreClock = new Sensor("GPU Core", 0, SensorType.Clock, this);
+      this.memoryClock = new Sensor("GPU Memory", 1, SensorType.Clock, this);
+      this.coreVoltage = new Sensor("GPU Core", 0, SensorType.Voltage, this);
+      Update();                   
+    }
+
+    public string Name {
+      get { return name; }
+    }
+
+    public string Identifier {
+      get { return "/atigpu/" + adapterIndex; }
+    }
+
+    public Image Icon {
+      get { return icon; }
+    }
+
+    public ISensor[] Sensors {
+      get {
+        return new ISensor[] { coreVoltage, coreClock, memoryClock, temperature, 
+          fan };
+      }
+    }
+
+    public string GetReport() {
+      return null;
+    }
+
+    public void Update() {
+      ADLTemperature adlt = new ADLTemperature();
+      ADL.ADL_Overdrive5_Temperature_Get(adapterIndex, 0, ref adlt);
+      temperature.Value = 0.001f * adlt.Temperature;
+
+      ADLFanSpeedValue adlf = new ADLFanSpeedValue();
+      adlf.SpeedType = ADL.ADL_DL_FANCTRL_SPEED_TYPE_RPM;
+      ADL.ADL_Overdrive5_FanSpeed_Get(adapterIndex, 0, ref adlf);
+      fan.Value = adlf.FanSpeed;
+
+      ADLPMActivity adlp = new ADLPMActivity();
+      ADL.ADL_Overdrive5_CurrentActivity_Get(adapterIndex, ref adlp);
+      coreClock.Value = 0.01f * adlp.EngineClock;
+      memoryClock.Value = 0.01f * adlp.MemoryClock;
+      coreVoltage.Value = 0.001f * adlp.Vddc;
+    }
+
+    #pragma warning disable 67
+    public event SensorEventHandler SensorAdded;
+    public event SensorEventHandler SensorRemoved;
+    #pragma warning restore 67
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/ATI/ATIGroup.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/ATI/ATIGroup.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,111 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenHardwareMonitor.Hardware.ATI {
+  public class ATIGroup : IGroup {
+
+    private List<ATIGPU> hardware = new List<ATIGPU>();
+    private StringBuilder report = new StringBuilder();
+
+    public ATIGroup() {
+      try {
+        if (ADL.ADL_Main_Control_Create(1) == ADL.ADL_SUCCESS) {
+          int numberOfAdapters = 0;
+          ADL.ADL_Adapter_NumberOfAdapters_Get(ref numberOfAdapters);
+
+          report.AppendLine("AMD Display Library");
+          report.AppendLine();
+          report.Append("Numer of adapters: "); 
+          report.AppendLine(numberOfAdapters.ToString());
+          report.AppendLine();
+
+          if (numberOfAdapters > 0) {
+            ADLAdapterInfo[] adapterInfo = new ADLAdapterInfo[numberOfAdapters];
+            if (ADL.ADL_Adapter_AdapterInfo_Get(adapterInfo) == ADL.ADL_SUCCESS)
+              for (int i = 0; i < numberOfAdapters; i++) {
+                int isActive;
+                ADL.ADL_Adapter_Active_Get(adapterInfo[i].AdapterIndex,
+                  out isActive);
+
+                report.Append("AdapterIndex: "); 
+                report.AppendLine(i.ToString());
+                report.Append("isActive: "); 
+                report.AppendLine(isActive.ToString());
+                report.Append("AdapterName: "); 
+                report.AppendLine(adapterInfo[i].AdapterName);     
+                report.Append("UDID: ");
+                report.AppendLine(adapterInfo[i].UDID);
+                report.AppendLine();
+
+                if (isActive == 1) {
+                  int adapterID;
+                  ADL.ADL_Adapter_ID_Get(adapterInfo[i].AdapterIndex,
+                    out adapterID);
+
+                  if (adapterID > 0 && adapterInfo[i].UDID != "") {
+                    hardware.Add(new ATIGPU(
+                      adapterInfo[i].AdapterName,
+                      adapterInfo[i].AdapterIndex));
+                  }
+                }
+              }
+          }
+        }
+      } catch (DllNotFoundException) { } catch (EntryPointNotFoundException) { }
+    }
+
+    public IHardware[] Hardware {
+      get {
+        return hardware.ToArray();
+      }
+    }
+
+    public string GetReport() {
+      return report.ToString();
+    }
+
+    public void Close() {
+      try {
+        ADL.ADL_Main_Control_Destroy();
+      } catch (Exception) { }
+    }
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/CPU/AMD10CPU.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/CPU/AMD10CPU.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,113 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Text;
+
+namespace OpenHardwareMonitor.Hardware.CPU {
+  
+  public class AMD10CPU : IHardware {
+    private string name;
+    private Image icon;
+
+    private uint pciAddress;
+
+    private Sensor coreTemperature;
+
+    private const ushort PCI_AMD_VENDOR_ID = 0x1022;
+    private const ushort PCI_AMD_10H_MISCELLANEOUS_DEVICE_ID = 0x1203;
+    private const uint REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4;
+
+    public AMD10CPU(string name, uint family, uint model, uint stepping, 
+      uint[,] cpuidData, uint[,] cpuidExtData) {
+      
+      this.name = name;
+      this.icon = Utilities.EmbeddedResources.GetImage("cpu.png");     
+
+      uint coreCount = 1;
+      if (cpuidExtData.GetLength(0) > 8)
+        coreCount = (cpuidExtData[8, 2] & 0xFF) + 1;
+      
+      // AMD family 10h processors support only one temperature sensor
+      coreTemperature = new Sensor("Core", 0, SensorType.Temperature, this);
+
+      pciAddress = WinRing0.FindPciDeviceById(PCI_AMD_VENDOR_ID, 
+        PCI_AMD_10H_MISCELLANEOUS_DEVICE_ID, 0);
+      Update();                   
+    }
+
+    public string Name {
+      get { return name; }
+    }
+
+    public string Identifier {
+      get { return "/amdcpu/0"; }
+    }
+
+    public Image Icon {
+      get { return icon; }
+    }
+
+    public ISensor[] Sensors {
+      get {
+        return new ISensor[] { coreTemperature };
+      }
+    }
+
+    public string GetReport() {
+      return null;
+    }
+
+    public void Update() {
+      if (pciAddress == 0xFFFFFFFF)
+        return;
+
+      uint value;      
+      if (WinRing0.ReadPciConfigDwordEx(pciAddress, 
+        REPORTED_TEMPERATURE_CONTROL_REGISTER, out value)) 
+        coreTemperature.Value = ((value >> 21) & 0x7FF) / 8.0f;      
+    }
+
+    #pragma warning disable 67
+    public event SensorEventHandler SensorAdded;
+    public event SensorEventHandler SensorRemoved;
+    #pragma warning restore 67
+
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/CPU/CPUGroup.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/CPU/CPUGroup.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,208 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenHardwareMonitor.Hardware.CPU {
+
+  public class CPUGroup : IGroup { 
+    private List<IHardware> hardware = new List<IHardware>();
+
+    private string cpuBrandString;
+    private string cpuVendor;
+    private uint[,] cpuidData;
+    private uint[,] cpuidExtData;
+
+    private uint family;
+    private uint model;
+    private uint stepping;
+
+    private static uint CPUID = 0;
+    private static uint CPUID_EXT = 0x80000000;
+
+    public static void AppendRegister(StringBuilder b, uint value) {
+      b.Append((char)((value) & 0xff));
+      b.Append((char)((value >> 8) & 0xff));
+      b.Append((char)((value >> 16) & 0xff));
+      b.Append((char)((value >> 24) & 0xff));
+    }
+
+    public CPUGroup() {
+
+      if (!WinRing0.IsAvailable) 
+        return;
+
+      if (WinRing0.IsCpuid()) {
+        uint maxCPUID = 0;
+        uint maxCPUID_EXT = 0;
+        uint eax, ebx, ecx, edx;
+
+        
+        if (WinRing0.Cpuid(CPUID, out eax, out ebx, out ecx, out edx)) {
+          maxCPUID = eax;
+          StringBuilder vendorBuilder = new StringBuilder();
+          AppendRegister(vendorBuilder, ebx);
+          AppendRegister(vendorBuilder, edx);
+          AppendRegister(vendorBuilder, ecx);
+          cpuVendor = vendorBuilder.ToString();
+
+          eax = ebx = ecx = edx = 0;
+          if (WinRing0.Cpuid(CPUID_EXT, out eax, out ebx, out ecx, out edx)) {
+            maxCPUID_EXT = eax - CPUID_EXT;
+          }
+        }
+        if (maxCPUID == 0 || maxCPUID_EXT == 0)
+          return;        
+
+        cpuidData = new uint[maxCPUID + 1, 4];
+        for (uint i = 0; i < (maxCPUID + 1); i++)
+          WinRing0.Cpuid(CPUID + i, out cpuidData[i, 0], out cpuidData[i, 1],
+            out cpuidData[i, 2], out cpuidData[i, 3]);
+
+        cpuidExtData = new uint[maxCPUID_EXT + 1, 4];
+        for (uint i = 0; i < (maxCPUID_EXT + 1); i++)
+          WinRing0.Cpuid(CPUID_EXT + i, out cpuidExtData[i, 0],
+            out cpuidExtData[i, 1], out cpuidExtData[i, 2],
+            out cpuidExtData[i, 3]);
+
+        StringBuilder nameBuilder = new StringBuilder();
+        for (uint i = 2; i <= 4; i++) {
+          if (WinRing0.Cpuid(CPUID_EXT + i, out eax, out ebx, out ecx, out edx)) 
+          {
+            AppendRegister(nameBuilder, eax);
+            AppendRegister(nameBuilder, ebx);
+            AppendRegister(nameBuilder, ecx);
+            AppendRegister(nameBuilder, edx);
+          }
+        }
+        cpuBrandString = nameBuilder.ToString();
+        nameBuilder.Replace("(R)", " ");
+        nameBuilder.Replace("(TM)", " ");
+        nameBuilder.Replace("(tm)", " ");
+        nameBuilder.Replace("CPU", "");
+        for (int i = 0; i < 10; i++) nameBuilder.Replace("  ", " ");
+        string name = nameBuilder.ToString();
+        if (name.Contains("@"))
+          name = name.Remove(name.LastIndexOf('@')); 
+        name = name.Trim();
+
+        this.family = ((cpuidData[1, 0] & 0x0FF00000) >> 20) +
+          ((cpuidData[1, 0] & 0x0F00) >> 8);
+        this.model = ((cpuidData[1, 0] & 0x0F0000) >> 12) +
+          ((cpuidData[1, 0] & 0xF0) >> 4);
+        this.stepping = (cpuidData[1, 0] & 0x0F);
+
+        switch (cpuVendor) {
+          case "GenuineIntel":
+            // check if processor supports a digital thermal sensor
+            if (maxCPUID >= 6 && (cpuidData[6, 0] & 1) != 0) 
+              hardware.Add(new IntelCPU(name, family, model, stepping, 
+                cpuidData, cpuidExtData));
+            break;
+          case "AuthenticAMD":                       
+            // check if processor supports a digital thermal sensor            
+            if (maxCPUID_EXT >= 7 && (cpuidExtData[7, 3] & 1) != 0) {
+              switch (family) {
+                case 0x10:
+                  hardware.Add(new AMD10CPU(name, family, model, stepping,
+                    cpuidData, cpuidExtData));
+                  break;
+                default:
+                  break;
+              }
+            }
+            break;
+          default:
+            break;
+        }
+      }
+    }
+
+    public IHardware[] Hardware {
+      get {
+        return hardware.ToArray();
+      }
+    }
+
+    private void AppendCpuidData(StringBuilder r, uint[,] data, uint offset) {
+      for (int i = 0; i < data.GetLength(0); i++) {
+        r.Append(" ");
+        r.Append((i + offset).ToString("X8"));
+        for (int j = 0; j < 4; j++) {
+          r.Append("  ");
+          r.Append(data[i, j].ToString("X8"));
+        }
+        r.AppendLine();
+      }
+    }
+
+    public string GetReport() {
+      if (hardware.Count == 0)
+        return null;
+
+      StringBuilder r = new StringBuilder();
+
+      r.AppendLine("CPUID");
+      r.AppendLine();
+      r.AppendFormat("Processor Vendor: {0}{1}", cpuVendor, 
+        Environment.NewLine);
+      r.AppendFormat("Processor Brand: {0}{1}", cpuBrandString, 
+        Environment.NewLine);
+      r.AppendFormat("Family: 0x{0}{1}", family.ToString("X"),
+        Environment.NewLine);
+      r.AppendFormat("Model: 0x{0}{1}", model.ToString("X"),
+        Environment.NewLine);
+      r.AppendFormat("Stepping: 0x{0}{1}", stepping.ToString("X"),
+        Environment.NewLine);
+      r.AppendLine();
+
+      r.AppendLine("CPUID Return Values");
+      r.AppendLine();
+
+      r.AppendLine(" Function  EAX       EBX       ECX       EDX");
+      AppendCpuidData(r, cpuidData, CPUID);
+      AppendCpuidData(r, cpuidExtData, CPUID_EXT);
+      r.AppendLine();
+
+      return r.ToString();
+    }
+
+    public void Close() { }
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/CPU/IntelCPU.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/CPU/IntelCPU.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,151 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Reflection;
+using System.Text;
+
+namespace OpenHardwareMonitor.Hardware.CPU {
+  public class IntelCPU : IHardware {
+
+    private string name;
+    private Image icon;
+
+    private Sensor[] coreTemperatures;
+
+    private float tjMax = 0;   
+
+    private const uint IA32_THERM_STATUS_MSR = 0x019C;
+
+    public IntelCPU(string name, uint family, uint model, uint stepping, 
+      uint[,] cpuidData, uint[,] cpuidExtData) {
+      
+      this.name = name;
+      this.icon = Utilities.EmbeddedResources.GetImage("cpu.png");
+      
+      uint coreCount = 1;
+      if (cpuidData.GetLength(0) > 4)
+        coreCount = ((cpuidData[4, 0] >> 26) & 0x3F) + 1;
+
+      switch (family) {
+        case 0x06: {
+          switch (model) {
+            case 0x0F: // Intel Core 65nm
+              switch (stepping) {
+                case 0x06: // B2
+                  switch (coreCount) {
+                    case 2:
+                      tjMax = 80; break;
+                    case 4:
+                      tjMax = 90; break;
+                    default:
+                      tjMax = 85; break;
+                  }
+                  tjMax = 80; break;
+                case 0x0B: // G0
+                  tjMax = 90; break;
+                case 0x0D: // M0
+                  tjMax = 85; break;
+                default:
+                  tjMax = 85; break;
+              } break;
+            case 0x1c: // Intel Atom 
+              tjMax = 90; break;
+            case 0x17: // Intel Core 45nm
+              tjMax = 100; break;
+            default:
+              tjMax = 100; break;
+          }
+        } break;
+        default: tjMax = 100; break;
+      }
+
+      coreTemperatures = new Sensor[coreCount];
+      for (int i = 0; i < coreTemperatures.Length; i++)
+        coreTemperatures[i] =
+          new Sensor("Core #" + (i + 1), i, tjMax, SensorType.Temperature, 
+            this);
+
+      Update();                   
+    }
+
+    public string Name {
+      get { return name; }
+    }
+
+    public string Identifier {
+      get { return "/intelcpu/0"; }
+    }
+
+    public Image Icon {
+      get { return icon; }
+    }
+
+    public ISensor[] Sensors {
+      get {
+        return coreTemperatures;
+      }
+    }
+
+    public string GetReport() {
+      return null;
+    }
+
+    public void Update() {
+
+      uint eax = 0, edx = 0;      
+      for (int i = 0; i < coreTemperatures.Length; i++) {
+        if (WinRing0.RdmsrPx(
+          IA32_THERM_STATUS_MSR, ref eax, ref edx, (UIntPtr)(1 << i))) 
+        {
+          // if reading is valid
+          if ((eax & 0x80000000) != 0) {
+            // get the dist from tjMax from bits 22:16
+            coreTemperatures[i].Value = tjMax - ((eax & 0x007F0000) >> 16);
+          }
+        }        
+      }  
+    }
+
+    #pragma warning disable 67
+    public event SensorEventHandler SensorAdded;
+    public event SensorEventHandler SensorRemoved;
+    #pragma warning restore 67
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/HDD/HDD.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/HDD/HDD.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,110 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace OpenHardwareMonitor.Hardware.HDD {
+  public class HDD : IHardware {
+
+    private const int UPDATE_DIVIDER = 30; // update only every 30s
+
+    private string name;
+    private IntPtr handle;
+    private int drive;
+    private int attribute;    
+    private Image icon;
+    private Sensor temperature;
+    private int count;
+    
+
+    public HDD(string name, IntPtr handle, int drive, int attribute) {
+      this.name = name;
+      this.handle = handle;
+      this.drive = drive;
+      this.attribute = attribute;
+      this.count = 0;
+      this.icon = Utilities.EmbeddedResources.GetImage("hdd.png");
+      this.temperature = new Sensor("HDD", 0, SensorType.Temperature, this);
+      Update();
+    }
+
+
+    public string Name {
+      get { return name; }
+    }
+
+    public string Identifier {
+      get { return "/hdd/" + drive; }
+    }
+
+    public Image Icon {
+      get { return icon; }
+    }
+
+    public ISensor[] Sensors {
+      get {
+        return new ISensor[] { temperature };
+      }
+    }
+
+    public string GetReport() {
+      return null;
+    }
+
+    public void Update() {
+      if (count == 0) {
+        SMART.DriveAttribute[] attributes = SMART.ReadSmart(handle, drive);
+        temperature.Value = attributes[attribute].RawValue[0];
+      } else {
+        temperature.Value = temperature.Value;
+      }
+
+      count++; count %= UPDATE_DIVIDER; 
+    }
+
+    public void Close() {
+      SMART.CloseHandle(handle);
+    }
+
+    #pragma warning disable 67
+    public event SensorEventHandler SensorAdded;
+    public event SensorEventHandler SensorRemoved;
+    #pragma warning restore 67
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/HDD/HDDGroup.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/HDD/HDDGroup.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,101 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+
+namespace OpenHardwareMonitor.Hardware.HDD {
+  public class HDDGroup : IGroup {
+
+    private const int MAX_DRIVES = 32;
+
+    private List<HDD> hardware = new List<HDD>();
+
+    public HDDGroup() {
+
+      int p = (int)System.Environment.OSVersion.Platform;
+      if ((p != 4) && (p != 128)) {
+        for (int drive = 0; drive < MAX_DRIVES; drive++) {
+          IntPtr handle = SMART.OpenPhysicalDrive(drive);
+
+          if (handle == SMART.INVALID_HANDLE_VALUE)
+            continue;
+
+          if (SMART.EnableSmart(handle, drive)) {
+
+            string name = SMART.ReadName(handle, drive);
+            if (name != null) {
+
+              SMART.DriveAttribute[] attributes =
+                SMART.ReadSmart(handle, drive);
+
+              int attribute = -1;
+              for (int i = 0; i < attributes.Length; i++) {
+                if (attributes[i].ID == SMART.AttributeID.Temperature) {
+                  attribute = i;
+                  break;
+                }
+              }
+
+              if (attribute >= 0) {
+                hardware.Add(new HDD(name, handle, drive, attribute));
+                continue;
+              }
+            }
+          }
+          SMART.CloseHandle(handle);
+        }
+      }
+    }
+
+
+    public IHardware[] Hardware {
+      get {
+        return hardware.ToArray();
+      }
+    }
+
+    public string GetReport() {
+      return null;
+    }
+
+    public void Close() {
+      foreach (HDD hdd in hardware) 
+        hdd.Close();
+    }
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/HDD/SMART.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/HDD/SMART.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,337 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace OpenHardwareMonitor.Hardware.HDD {
+    
+  public class SMART {
+
+    [Flags]
+    public enum Status : ushort {
+      PreFailureWarranty = 0x01,
+      OnLineCollection = 0x02,
+      Performance = 0x04,
+      ErrorRate = 0x08,
+      EventCount = 0x10,
+      SelfPreserving = 0x20
+    }
+
+    public enum AttributeID : byte {
+      ReadErrorRate = 0x01,
+      ThroughputPerformance = 0x02,
+      SpinUpTime = 0x03,
+      StartStopCount = 0x04,
+      ReallocatedSectorsCount = 0x05,
+      ReadChannelMargin = 0x06,
+      SeekErrorRate = 0x07,
+      SeekTimePerformance = 0x08,
+      PowerOnHours = 0x09,
+      SpinRetryCount = 0x0A,
+      RecalibrationRetries = 0x0B,
+      PowerCycleCount = 0x0C,
+      SoftReadErrorRate = 0x0D,
+      Temperature = 0xC2,
+      HardwareECCRecovered = 0xC3,
+      ReallocationEventCount = 0xC4,
+      CurrentPendingSectorCount = 0xC5,
+      UncorrectableSectorCount = 0xC6,
+      UltraDMACRCErrorCount = 0xC7,
+      WriteErrorRate = 0xC8
+    }
+
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct DriveAttribute {
+      public AttributeID ID;
+      public Status StatusFlags;
+      public byte AttrValue;
+      public byte WorstValue;
+      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
+      public byte[] RawValue;
+      public byte Reserved;
+    };
+
+    [Flags]
+    private enum AccessMode : uint {     
+      Read = 0x80000000,    
+      Write = 0x40000000,     
+      Execute = 0x20000000,     
+      All = 0x10000000
+    }
+
+    [Flags]
+    private enum ShareMode : uint {
+      None = 0,     
+      Read = 1,     
+      Write = 2,    
+      Delete = 4
+    }
+
+    private enum CreationMode : uint {
+      New = 1,
+      CreateAlways = 2,    
+      OpenExisting = 3,    
+      OpenAlways = 4,    
+      TruncateExisting = 5
+    }
+
+    [Flags]
+    private enum FileAttribute : uint {
+      Readonly = 0x00000001,
+      Hidden = 0x00000002,
+      System = 0x00000004,
+      Directory = 0x00000010,
+      Archive = 0x00000020,
+      Device = 0x00000040,
+      Normal = 0x00000080,
+      Temporary = 0x00000100,
+      SparseFile = 0x00000200,
+      ReparsePoint = 0x00000400,
+      Compressed = 0x00000800,
+      Offline = 0x00001000,
+      NotContentIndexed = 0x00002000,
+      Encrypted = 0x00004000,
+    }
+
+    private enum DriveCommand : uint {
+      GetVersion = 0x00074080,
+      SendDriveCommand = 0x0007c084,
+      ReceiveDriveData = 0x0007c088
+    }
+
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    private struct CommandBlockRegisters {
+      public byte Features;         
+      public byte SectorCount;      
+      public byte LBALow;       
+      public byte LBAMid;           
+      public byte LBAHigh;        
+      public byte Device;       
+      public byte Command;           
+      public byte Reserved;                  
+    }
+
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    private struct DriveCommandParameter {
+      private uint BufferSize;           
+      public CommandBlockRegisters Registers;           
+      public byte DriveNumber;   
+      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 19)]
+      public byte[] Reserved;                                
+    }
+
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    private struct DriverStatus {
+      public byte DriverError;   
+      public byte IDEError;             
+      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
+      public byte[] Reserved;               
+    }
+
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    private struct DriveCommandResult {
+      public uint BufferSize;
+      public DriverStatus DriverStatus;
+    } 
+
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    private struct DriveSmartReadResult {
+      public uint BufferSize;           
+      public DriverStatus DriverStatus;
+      public byte Version;
+      public byte Reserved;
+      [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_DRIVE_ATTRIBUTES)]
+      public DriveAttribute[] Attributes;                                                                                       
+    }
+
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    private struct Identify {
+      public ushort GeneralConfiguration;
+      public ushort NumberOfCylinders;
+      public ushort Reserved;
+      public ushort NumberOfHeads;
+      public ushort UnformattedBytesPerTrack;
+      public ushort UnformattedBytesPerSector;
+      public ushort SectorsPerTrack;
+      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+      public ushort[] VendorUnique;
+      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
+      public byte[] SerialNumber;
+      public ushort BufferType;
+      public ushort BufferSectorSize;
+      public ushort NumberOfEccBytes;
+      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
+      public byte[] FirmwareRevision;
+      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
+      public byte[] ModelNumber;
+      public ushort MoreVendorUnique;
+      public ushort DoubleWordIo;
+      public ushort Capabilities;
+      public ushort MoreReserved;
+      public ushort PioCycleTimingMode;
+      public ushort DmaCycleTimingMode;
+      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 406)]
+      public byte[] More;
+    }
+
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    private struct DriveIdentifyResult {
+      public uint BufferSize;
+      public DriverStatus DriverStatus;
+      public Identify Identify;
+    } 
+
+    public static readonly IntPtr INVALID_HANDLE_VALUE = (IntPtr)(-1);
+
+    private const byte SMART_CMD = 0xB0;
+    private const byte ID_CMD = 0xEC;
+    
+    private const byte SMART_READ_DATA = 0xD0;
+    private const byte SMART_ENABLE_OPERATIONS = 0xD8;
+    
+    private const byte SMART_LBA_MID = 0x4F;
+    private const byte SMART_LBA_HI = 0xC2;
+
+    private const int MAX_DRIVE_ATTRIBUTES = 512;
+
+    private const string KERNEL = "kernel32.dll";
+
+    [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
+    private static extern IntPtr CreateFile(string fileName, 
+      AccessMode desiredAccess, ShareMode shareMode, IntPtr securityAttributes,
+      CreationMode creationDisposition, FileAttribute flagsAndAttributes, 
+      IntPtr templateFilehandle);
+
+    [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
+    public static extern int CloseHandle(IntPtr handle);
+
+    [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
+    private static extern bool DeviceIoControl(IntPtr handle,
+      DriveCommand command, ref DriveCommandParameter parameter,
+      int parameterSize, out DriveSmartReadResult result, int resultSize, 
+      out uint bytesReturned, IntPtr overlapped);
+
+    [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
+    private static extern bool DeviceIoControl(IntPtr handle,
+      DriveCommand command, ref DriveCommandParameter parameter,
+      int parameterSize, out DriveCommandResult result, int resultSize,
+      out uint bytesReturned, IntPtr overlapped);
+
+    [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
+    private static extern bool DeviceIoControl(IntPtr handle,
+      DriveCommand command, ref DriveCommandParameter parameter,
+      int parameterSize, out DriveIdentifyResult result, int resultSize,
+      out uint bytesReturned, IntPtr overlapped);
+
+    public static IntPtr OpenPhysicalDrive(int driveNumber) {
+      return CreateFile(@"\\.\PhysicalDrive" + driveNumber,
+        AccessMode.Read | AccessMode.Write, ShareMode.Read | ShareMode.Write,
+        IntPtr.Zero, CreationMode.OpenExisting, FileAttribute.Device,
+        IntPtr.Zero);
+    }
+
+    public static bool EnableSmart(IntPtr handle, int driveNumber) {
+      DriveCommandParameter parameter = new DriveCommandParameter();
+      DriveCommandResult result;
+      uint bytesReturned;
+
+      parameter.DriveNumber = (byte)driveNumber;
+      parameter.Registers.Features = SMART_ENABLE_OPERATIONS;
+      parameter.Registers.LBAMid = SMART_LBA_MID;
+      parameter.Registers.LBAHigh = SMART_LBA_HI;
+      parameter.Registers.Command = SMART_CMD;
+
+      return DeviceIoControl(handle, DriveCommand.SendDriveCommand, 
+        ref parameter, Marshal.SizeOf(parameter), out result,
+        Marshal.SizeOf(typeof(DriveCommandResult)), out bytesReturned, 
+        IntPtr.Zero);
+    }
+
+    public static DriveAttribute[] ReadSmart(IntPtr handle, int driveNumber) {
+      DriveCommandParameter parameter = new DriveCommandParameter();
+      DriveSmartReadResult result;
+      uint bytesReturned;
+
+      parameter.DriveNumber = (byte)driveNumber;
+      parameter.Registers.Features = SMART_READ_DATA;
+      parameter.Registers.LBAMid = SMART_LBA_MID;
+      parameter.Registers.LBAHigh = SMART_LBA_HI;
+      parameter.Registers.Command = SMART_CMD;
+
+      bool valid = DeviceIoControl(handle, DriveCommand.ReceiveDriveData,
+        ref parameter, Marshal.SizeOf(parameter), out result,
+        Marshal.SizeOf(typeof(DriveSmartReadResult)), out bytesReturned,
+        IntPtr.Zero);
+
+      if (!valid)
+        return null;
+      else
+        return result.Attributes;
+    }
+
+    public static string ReadName(IntPtr handle, int driveNumber) {
+      DriveCommandParameter parameter = new DriveCommandParameter();
+      DriveIdentifyResult result;
+      uint bytesReturned;
+
+      parameter.DriveNumber = (byte)driveNumber;
+      parameter.Registers.Command = ID_CMD;
+
+      bool valid = DeviceIoControl(handle, DriveCommand.ReceiveDriveData,
+        ref parameter, Marshal.SizeOf(parameter), out result,
+        Marshal.SizeOf(typeof(DriveIdentifyResult)), out bytesReturned,
+        IntPtr.Zero);
+
+      if (!valid)
+        return null;
+      else {
+
+        byte[] bytes = result.Identify.ModelNumber;
+        char[] chars = new char[bytes.Length];
+        for (int i = 0; i < bytes.Length; i += 2) {
+          chars[i] = (char)bytes[i + 1];
+          chars[i + 1] = (char)bytes[i];
+        }
+
+        return new string(chars).Trim();
+      }
+    }
+
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/IGroup.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/IGroup.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,52 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+
+namespace OpenHardwareMonitor.Hardware {
+
+  public interface IGroup {
+
+    IHardware[] Hardware { get; }
+
+    string GetReport();
+
+    void Close();
+  }
+
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/IHardware.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/IHardware.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,62 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace OpenHardwareMonitor.Hardware {
+
+  public delegate void SensorEventHandler(ISensor sensor);
+
+  public interface IHardware {
+
+    string Name { get; }
+    string Identifier { get; }
+
+    Image Icon { get; }
+
+    string GetReport();
+
+    void Update();
+
+    ISensor[] Sensors { get; }
+
+    event SensorEventHandler SensorAdded;
+    event SensorEventHandler SensorRemoved;
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/ISensor.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/ISensor.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,66 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+
+namespace OpenHardwareMonitor.Hardware {
+
+  public enum SensorType {
+    Voltage,
+    Clock,
+    Temperature,
+    Fan    
+  }
+
+  public interface ISensorEntry {
+    float Value { get; }
+    DateTime Time { get; }
+  }
+
+  public interface ISensor {
+    SensorType SensorType { get; }
+    string Name { get; set; }
+    int Index { get; }
+    float? Value { get; }
+    float? Min { get; }
+    float? Max { get; }
+    float? Limit { get; set; }
+    IEnumerable<ISensorEntry> Plot { get; }
+  }
+
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/LPC/Chip.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/LPC/Chip.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,17 @@
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenHardwareMonitor.Hardware.LPC {
+
+  public enum Chip : ushort {
+    Unknown = 0,
+    IT8716F = 0x8716,
+    IT8718F = 0x8718,
+    IT8720F = 0x8720,
+    IT8726F = 0x8726,
+    W83627DHG = 0xA020
+  }
+
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/LPC/IT87.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/LPC/IT87.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,225 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Text;
+
+namespace OpenHardwareMonitor.Hardware.LPC {
+  public class IT87 : IHardware {
+
+    private string name;
+    private Image icon;
+        
+    private bool available = false;
+    private Chip chip;
+    private ushort address;
+
+    private Sensor[] temperatures;
+    private Sensor[] fans;
+    private Sensor[] voltages;
+    private List<ISensor> active = new List<ISensor>();
+    private float[] voltageGains;
+
+   
+    // Consts
+    private const byte ITE_VENDOR_ID = 0x90;
+       
+    // Environment Controller
+    private const byte ADDRESS_REGISTER_OFFSET = 0x05;
+    private const byte DATA_REGISTER_OFFSET = 0x06;
+
+    // Environment Controller Registers    
+    private const byte CONFIGURATION_REGISTER = 0x00;
+    private const byte TEMPERATURE_BASE_REG = 0x29;
+    private const byte VENDOR_ID_REGISTER = 0x58;
+    private const byte FAN_TACHOMETER_16_BIT_ENABLE_REGISTER = 0x0c;
+    private byte[] FAN_TACHOMETER_REG = 
+      new byte[] { 0x0d, 0x0e, 0x0f, 0x80, 0x82 };
+    private byte[] FAN_TACHOMETER_EXT_REG =
+      new byte[] { 0x18, 0x19, 0x1a, 0x81, 0x83 };
+    private const byte VOLTAGE_BASE_REG = 0x20;  
+    
+
+    private byte ReadByte(byte register) {
+      WinRing0.WriteIoPortByte(
+        (ushort)(address + ADDRESS_REGISTER_OFFSET), register);
+      return WinRing0.ReadIoPortByte((ushort)(address + DATA_REGISTER_OFFSET));
+    }
+
+    public IT87(Chip chip, ushort address) {
+      
+      this.chip = chip;
+      this.address = address;
+
+      switch (chip) {
+        case Chip.IT8716F: name = "ITE IT8716F"; break;
+        case Chip.IT8718F: name = "ITE IT8718F"; break;
+        case Chip.IT8720F: name = "ITE IT8720F"; break;
+        case Chip.IT8726F: name = "ITE IT8726F"; break;
+        default: return;
+      }
+      
+      // Check vendor id
+      byte vendorId = ReadByte(VENDOR_ID_REGISTER);      
+      if (vendorId != ITE_VENDOR_ID)
+        return;
+
+      // Bit 0x10 of the configuration register should always be 1
+      if ((ReadByte(CONFIGURATION_REGISTER) & 0x10) == 0)
+        return;
+
+      temperatures = new Sensor[3];
+      for (int i = 0; i < temperatures.Length; i++) 
+        temperatures[i] = new Sensor("Temperature #" + (i + 1), i,
+          SensorType.Temperature, this);
+
+      fans = new Sensor[4];
+      for (int i = 0; i < fans.Length; i++)
+        fans[i] = new Sensor("Fan #" + (i + 1), i, SensorType.Fan, this);
+
+      voltageGains = new float[] { 
+        1, 1, 1, (6.8f / 10 + 1), 1, 1, 1, 1, 1 };
+
+      voltages = new Sensor[2];
+      voltages[0] = new Sensor("CPU VCore", 0, SensorType.Voltage, this);
+      voltages[1] = new Sensor("Battery", 8, SensorType.Voltage, this);           
+
+      available = true;
+      icon = Utilities.EmbeddedResources.GetImage("chip.png");
+    }
+
+    public bool IsAvailable {
+      get { return available; } 
+    }
+
+    public string Name {
+      get { return name; }
+    }
+
+    public string Identifier {
+      get { return "/lpc/it87"; }
+    }
+
+    public Image Icon {
+      get { return icon; }
+    }
+
+    public ISensor[] Sensors {
+      get { return active.ToArray(); }
+    }
+
+    public string GetReport() {
+      StringBuilder r = new StringBuilder();
+
+      r.AppendLine("LPC IT87");
+      r.AppendLine();
+      r.Append("Chip ID: 0x"); r.AppendLine(chip.ToString("X"));
+      r.Append("Chip Name: "); r.AppendLine(name);
+      r.Append("Base Address: 0x"); r.AppendLine(address.ToString("X"));
+      r.AppendLine();
+      r.AppendLine("Environment Controller Registers");
+      r.AppendLine();
+
+      r.AppendLine("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
+      r.AppendLine();
+      for (int i = 0; i <= 0xA; i++) {
+        r.Append(" "); r.Append((i << 4).ToString("X2")); r.Append("  ");
+        for (int j = 0; j <= 0xF; j++) {
+          r.Append(" ");
+          r.Append(ReadByte((byte)((i << 4) | j)).ToString("X2"));
+        }
+        r.AppendLine();
+      }
+      r.AppendLine();
+
+      return r.ToString();
+    }
+
+    public void Update() {
+
+      foreach (Sensor sensor in voltages) {
+        int value = ReadByte((byte)(VOLTAGE_BASE_REG + sensor.Index));
+        sensor.Value = voltageGains[sensor.Index] * 0.001f * (value << 4);
+        if (sensor.Value > 0)
+          ActivateSensor(sensor);
+        else
+          DeactivateSensor(sensor);
+      }
+
+      foreach (Sensor sensor in temperatures) {
+        int value = ReadByte((byte)(TEMPERATURE_BASE_REG + sensor.Index));
+        sensor.Value = value;
+        if (value < 254)
+          ActivateSensor(sensor);
+        else
+          DeactivateSensor(sensor);
+      }
+
+      foreach (Sensor sensor in fans) {
+        int value = ReadByte(FAN_TACHOMETER_REG[sensor.Index]);
+        value |= ReadByte(FAN_TACHOMETER_EXT_REG[sensor.Index]) << 8;
+
+        if (value > 0) {
+          sensor.Value = (value < 0xffff) ? 1.35e6f / ((value) * 2) : 0;
+          ActivateSensor(sensor);
+        } else {
+          DeactivateSensor(sensor);
+        }
+      }      
+    }
+
+    private void ActivateSensor(Sensor sensor) {
+      if (!active.Contains(sensor)) {
+        active.Add(sensor);
+        SensorAdded(sensor);
+      }
+    }
+
+    private void DeactivateSensor(Sensor sensor) {
+      if (active.Contains(sensor)) {
+        active.Remove(sensor);
+        SensorRemoved(sensor);
+      }
+    }
+
+    public event SensorEventHandler SensorAdded;
+    public event SensorEventHandler SensorRemoved;
+
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/LPC/LPCGroup.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/LPC/LPCGroup.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,176 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+
+namespace OpenHardwareMonitor.Hardware.LPC {
+  public class LPCGroup : IGroup {
+    private List<IHardware> hardware = new List<IHardware>();
+
+    private Chip chip = Chip.Unknown;
+
+    // I/O Ports
+    private const ushort REGISTER_PORT = 0x2e;
+    private const ushort VALUE_PORT = 0x2f;
+
+    // Registers
+    private const byte CONFIGURATION_CONTROL_REGISTER = 0x02;
+    private const byte DEVCIE_SELECT_REGISTER = 0x07;
+    private const byte CHIP_ID_REGISTER = 0x20;
+    private const byte CHIP_REVISION_REGISTER = 0x21;
+
+    private static byte ReadByte(byte register) {
+      WinRing0.WriteIoPortByte(REGISTER_PORT, register);
+      return WinRing0.ReadIoPortByte(VALUE_PORT);
+    }
+
+    private static ushort ReadWord(byte register) {
+      ushort value;
+      WinRing0.WriteIoPortByte(REGISTER_PORT, register);
+      value = (ushort)(((ushort)WinRing0.ReadIoPortByte(VALUE_PORT)) << 8);
+      WinRing0.WriteIoPortByte(REGISTER_PORT, (byte)(register + 1));
+      value |= (ushort)WinRing0.ReadIoPortByte(VALUE_PORT);
+      return value;
+    }
+
+    private static void Select(byte logicalDeviceNumber) {
+      WinRing0.WriteIoPortByte(REGISTER_PORT, DEVCIE_SELECT_REGISTER);
+      WinRing0.WriteIoPortByte(VALUE_PORT, logicalDeviceNumber);
+    }
+
+    // IT87
+    private const ushort IT8716F_CHIP_ID = 0x8716;
+    private const ushort IT8718F_CHIP_ID = 0x8718;
+    private const ushort IT8720F_CHIP_ID = 0x8720;
+    private const ushort IT8726F_CHIP_ID = 0x8726;
+
+    private const byte IT87_ENVIRONMENT_CONTROLLER_LDN = 0x04;
+    private const byte IT87_ENVIRONMENT_CONTROLLER_BASE_ADDR_REG = 0x60;
+
+    private static void IT87Enter() {
+      WinRing0.WriteIoPortByte(REGISTER_PORT, 0x87);
+      WinRing0.WriteIoPortByte(REGISTER_PORT, 0x01);
+      WinRing0.WriteIoPortByte(REGISTER_PORT, 0x55);
+      WinRing0.WriteIoPortByte(REGISTER_PORT, 0x55);
+    }
+
+    internal static void IT87Exit() {
+      WinRing0.WriteIoPortByte(REGISTER_PORT, CONFIGURATION_CONTROL_REGISTER);
+      WinRing0.WriteIoPortByte(VALUE_PORT, 0x02);
+    }
+
+    // Winbond
+    private static void WinbondEnter() {
+      WinRing0.WriteIoPortByte(REGISTER_PORT, 0x87);
+      WinRing0.WriteIoPortByte(REGISTER_PORT, 0x87);
+    }
+
+    private static void WinbondExit() {
+      WinRing0.WriteIoPortByte(REGISTER_PORT, 0xAA);      
+    }
+
+    public LPCGroup() {
+      if (!WinRing0.IsAvailable)
+        return;
+
+      WinbondEnter();
+
+      byte id = ReadByte(CHIP_ID_REGISTER);
+      byte revision = ReadByte(CHIP_REVISION_REGISTER);
+      switch (id) {
+        case 0xA0:
+          switch (revision & 0xF0) {
+            case 0x20: chip = Chip.W83627DHG; break;
+            default: chip = Chip.Unknown; break;
+          } break;
+        default: chip = Chip.Unknown; break;
+      }
+      if (chip != Chip.Unknown) {
+
+        WinbondExit();
+
+        W83627DHG w83627dhg = new W83627DHG(revision);
+        if (w83627dhg.IsAvailable)
+          hardware.Add(w83627dhg);
+        return;
+      }
+
+      IT87Enter();
+
+      switch (ReadWord(CHIP_ID_REGISTER)) {
+        case 0x8716: chip = Chip.IT8716F; break;
+        case 0x8718: chip = Chip.IT8718F; break;
+        case 0x8720: chip = Chip.IT8720F; break;
+        case 0x8726: chip = Chip.IT8726F; break;
+        default: chip = Chip.Unknown; break;
+      }
+
+      if (chip != Chip.Unknown) {        
+        Select(IT87_ENVIRONMENT_CONTROLLER_LDN);
+        ushort address = ReadWord(IT87_ENVIRONMENT_CONTROLLER_BASE_ADDR_REG);
+        Thread.Sleep(1);
+        ushort verify = ReadWord(IT87_ENVIRONMENT_CONTROLLER_BASE_ADDR_REG);
+
+        IT87Exit();
+
+        if (address != verify || address == 0 || (address & 0xF007) != 0)
+          return;
+
+        IT87 it87 = new IT87(chip, address);
+        if (it87.IsAvailable)
+          hardware.Add(it87);
+        
+        return;
+      }                
+    }
+
+    public IHardware[] Hardware {
+      get {
+        return hardware.ToArray();
+      }
+    }
+
+    public string GetReport() {
+      return null;
+    }
+
+    public void Close() { }
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/LPC/W83627DHG.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/LPC/W83627DHG.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Text;
+
+namespace OpenHardwareMonitor.Hardware.LPC {
+  public class W83627DHG : IHardware {
+
+    private byte revision;
+
+    private string name;
+    private Image icon;
+
+    private bool available = false;
+
+    public W83627DHG(byte revision) {      
+      this.revision = revision;
+
+      this.name = "Winbond W83627DHG";
+      this.icon = Utilities.EmbeddedResources.GetImage("chip.png");
+    }
+
+    public bool IsAvailable {
+      get { return available; }
+    }
+
+    public string Name {
+      get { return name; }
+    }
+
+    public string Identifier {
+      get { return "/lpc/w83627dhg"; }
+    }
+
+    public Image Icon {
+      get { return icon; }
+    }
+
+    public ISensor[] Sensors {
+      get { return new ISensor[0]; }
+    }
+
+    public string GetReport() {
+      StringBuilder r = new StringBuilder();
+
+      r.AppendLine("LPC W83627DHG");
+      r.AppendLine();
+      r.Append("Chip revision: 0x"); r.AppendLine(revision.ToString("X"));     
+
+      return r.ToString();
+    }
+
+    public void Update() { }
+
+    #pragma warning disable 67
+    public event SensorEventHandler SensorAdded;
+    public event SensorEventHandler SensorRemoved;
+    #pragma warning restore 67
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/Nvidia/NVAPI.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/Nvidia/NVAPI.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,243 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace OpenHardwareMonitor.Hardware.Nvidia {
+
+  public enum NvStatus {
+    OK = 0,
+    ERROR = -1,
+    LIBRARY_NOT_FOUND = -2,
+    NO_IMPLEMENTATION = -3,
+    API_NOT_INTIALIZED = -4,
+    INVALID_ARGUMENT = -5,
+    NVIDIA_DEVICE_NOT_FOUND = -6,
+    END_ENUMERATION = -7,
+    INVALID_HANDLE = -8,
+    INCOMPATIBLE_STRUCT_VERSION = -9,
+    HANDLE_INVALIDATED = -10,
+    OPENGL_CONTEXT_NOT_CURRENT = -11,
+    NO_GL_EXPERT = -12,
+    INSTRUMENTATION_DISABLED = -13,
+    EXPECTED_LOGICAL_GPU_HANDLE = -100,
+    EXPECTED_PHYSICAL_GPU_HANDLE = -101,
+    EXPECTED_DISPLAY_HANDLE = -102,
+    INVALID_COMBINATION = -103,
+    NOT_SUPPORTED = -104,
+    PORTID_NOT_FOUND = -105,
+    EXPECTED_UNATTACHED_DISPLAY_HANDLE = -106,
+    INVALID_PERF_LEVEL = -107,
+    DEVICE_BUSY = -108,
+    NV_PERSIST_FILE_NOT_FOUND = -109,
+    PERSIST_DATA_NOT_FOUND = -110,
+    EXPECTED_TV_DISPLAY = -111,
+    EXPECTED_TV_DISPLAY_ON_DCONNECTOR = -112,
+    NO_ACTIVE_SLI_TOPOLOGY = -113,
+    SLI_RENDERING_MODE_NOTALLOWED = -114,
+    EXPECTED_DIGITAL_FLAT_PANEL = -115,
+    ARGUMENT_EXCEED_MAX_SIZE = -116,
+    DEVICE_SWITCHING_NOT_ALLOWED = -117,
+    TESTING_CLOCKS_NOT_SUPPORTED = -118,
+    UNKNOWN_UNDERSCAN_CONFIG = -119,
+    TIMEOUT_RECONFIGURING_GPU_TOPO = -120,
+    DATA_NOT_FOUND = -121,
+    EXPECTED_ANALOG_DISPLAY = -122,
+    NO_VIDLINK = -123,
+    REQUIRES_REBOOT = -124,
+    INVALID_HYBRID_MODE = -125,
+    MIXED_TARGET_TYPES = -126,
+    SYSWOW64_NOT_SUPPORTED = -127,
+    IMPLICIT_SET_GPU_TOPOLOGY_CHANGE_NOT_ALLOWED = -128,
+    REQUEST_USER_TO_CLOSE_NON_MIGRATABLE_APPS = -129,
+    OUT_OF_MEMORY = -130,
+    WAS_STILL_DRAWING = -131,
+    FILE_NOT_FOUND = -132,
+    TOO_MANY_UNIQUE_STATE_OBJECTS = -133,
+    INVALID_CALL = -134,
+    D3D10_1_LIBRARY_NOT_FOUND = -135,
+    FUNCTION_NOT_FOUND = -136
+  }  
+
+  public enum NvThermalController {
+    NONE = 0,
+    GPU_INTERNAL,  
+    ADM1032,
+    MAX6649,       
+    MAX1617,      
+    LM99,      
+    LM89,         
+    LM64,         
+    ADT7473,
+    SBMAX6649,
+    VBIOSEVT,  
+    OS,    
+    UNKNOWN = -1,
+  } 
+
+  public enum NvThermalTarget {
+    NONE = 0,
+    GPU = 1,
+    MEMORY = 2,
+    POWER_SUPPLY = 4,
+    BOARD = 8,
+    ALL = 15,
+    UNKNOWN = -1
+  };
+
+  [StructLayout(LayoutKind.Sequential)]
+  public struct NvSensor {
+    public NvThermalController Controller;
+    public int DefaultMinTemp;
+    public int DefaultMaxTemp;
+    public int CurrentTemp;
+    public NvThermalTarget Target;     
+  }
+
+  [StructLayout(LayoutKind.Sequential)]
+  public struct NvGPUThermalSettings {
+    public int Version;
+    public int Count;
+    [MarshalAs(UnmanagedType.ByValArray, 
+      SizeConst = NVAPI.MAX_THERMAL_SENSORS_PER_GPU)]
+    public NvSensor[] Sensor;
+  }
+
+  [StructLayout(LayoutKind.Sequential)]
+  public struct NvDisplayHandle {
+    private int handle;
+  }
+
+  [StructLayout(LayoutKind.Sequential)]
+  public struct NvPhysicalGpuHandle {
+    private int handle;
+  }
+
+  public class NVAPI {
+          
+    private const int SHORT_STRING_MAX = 64;
+
+    public const int MAX_THERMAL_SENSORS_PER_GPU = 3;
+    public const int MAX_PHYSICAL_GPUS = 64;
+    public static readonly int GPU_THERMAL_SETTINGS_VER =
+      Marshal.SizeOf(typeof(NvGPUThermalSettings)) | 0x10000;
+            
+    private delegate IntPtr nvapi_QueryInterfaceDelegate(uint id);
+    private delegate NvStatus NvAPI_InitializeDelegate();
+    private delegate NvStatus NvAPI_GPU_GetFullNameDelegate(
+      NvPhysicalGpuHandle gpuHandle, StringBuilder name);
+
+    public delegate NvStatus NvAPI_GPU_GetThermalSettingsDelegate(
+      NvPhysicalGpuHandle gpuHandle, int sensorIndex, 
+      ref NvGPUThermalSettings nvGPUThermalSettings);
+    public delegate NvStatus NvAPI_EnumNvidiaDisplayHandleDelegate(int thisEnum,
+      ref NvDisplayHandle displayHandle);
+    public delegate NvStatus NvAPI_GetPhysicalGPUsFromDisplayDelegate(
+      NvDisplayHandle displayHandle, [Out] NvPhysicalGpuHandle[] gpuHandles, 
+      out int gpuCount);
+    public delegate NvStatus NvAPI_EnumPhysicalGPUsDelegate(
+      [Out] NvPhysicalGpuHandle[] gpuHandles, out int gpuCount);
+
+    private static bool available = false;
+    private static nvapi_QueryInterfaceDelegate nvapi_QueryInterface;
+    private static NvAPI_InitializeDelegate NvAPI_Initialize;
+    private static NvAPI_GPU_GetFullNameDelegate _NvAPI_GPU_GetFullName;
+
+    public static NvAPI_GPU_GetThermalSettingsDelegate 
+      NvAPI_GPU_GetThermalSettings;
+    public static NvAPI_EnumNvidiaDisplayHandleDelegate
+      NvAPI_EnumNvidiaDisplayHandle;
+    public static NvAPI_GetPhysicalGPUsFromDisplayDelegate
+      NvAPI_GetPhysicalGPUsFromDisplay;
+    public static NvAPI_EnumPhysicalGPUsDelegate
+      NvAPI_EnumPhysicalGPUs;
+
+    public static NvStatus NvAPI_GPU_GetFullName(NvPhysicalGpuHandle gpuHandle,
+      out string name) {
+      StringBuilder builder = new StringBuilder(SHORT_STRING_MAX);
+      NvStatus status = _NvAPI_GPU_GetFullName(gpuHandle, builder);
+      name = builder.ToString();
+      return status;
+    }
+
+    private static string GetDllName() {
+      if (IntPtr.Size == 4) {
+        return "nvapi.dll";
+      } else {
+        return "nvapi64.dll";
+      }
+    }
+
+    private static void GetDelegate<T>(uint id, out T newDelegate) 
+      where T : class 
+    {
+      IntPtr ptr = nvapi_QueryInterface(id);
+      newDelegate = Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T;      
+    }
+
+    static NVAPI() { 
+      DllImportAttribute attribute = new DllImportAttribute(GetDllName());
+      attribute.CallingConvention = CallingConvention.Cdecl;
+      attribute.PreserveSig = true;
+      attribute.EntryPoint = "nvapi_QueryInterface";
+      PInvokeDelegateFactory.CreateDelegate(attribute,
+        out nvapi_QueryInterface);
+
+      try {
+        GetDelegate(0x0150E828, out NvAPI_Initialize);
+      } catch (DllNotFoundException) { return; } 
+        catch (ArgumentNullException) { return; }
+
+      if (NvAPI_Initialize() == NvStatus.OK) {
+        GetDelegate(0xE3640A56, out NvAPI_GPU_GetThermalSettings);
+        GetDelegate(0xCEEE8E9F, out _NvAPI_GPU_GetFullName);
+        GetDelegate(0x9ABDD40D, out NvAPI_EnumNvidiaDisplayHandle);
+        GetDelegate(0x34EF9506, out NvAPI_GetPhysicalGPUsFromDisplay);
+        GetDelegate(0xE5AC921F, out NvAPI_EnumPhysicalGPUs);
+        available = true;
+      }
+    }
+
+    public static bool IsAvailable {
+      get { return available; }
+    }
+
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/Nvidia/NvidiaGPU.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/Nvidia/NvidiaGPU.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,126 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace OpenHardwareMonitor.Hardware.Nvidia {
+  public class NvidiaGPU : IHardware {
+
+    private string name;
+    private Image icon;
+    private int adapterIndex;
+    private NvPhysicalGpuHandle handle;
+
+    private Sensor[] temperatures;
+
+    public NvidiaGPU(int adapterIndex, NvPhysicalGpuHandle handle) {
+      try {
+        string gpuName;
+        NVAPI.NvAPI_GPU_GetFullName(handle, out gpuName);
+        this.name = "NVIDIA " + gpuName;
+        this.icon = Utilities.EmbeddedResources.GetImage("nvidia.png");
+        this.adapterIndex = adapterIndex;
+        this.handle = handle;
+
+        NvGPUThermalSettings settings = GetThermalSettings();
+        temperatures = new Sensor[settings.Count];
+        for (int i = 0; i < temperatures.Length; i++) {
+          NvSensor sensor = settings.Sensor[i];
+          string name;
+          switch (sensor.Target) {
+            case NvThermalTarget.BOARD: name = "GPU Board"; break;
+            case NvThermalTarget.GPU: name = "GPU Core"; break;
+            case NvThermalTarget.MEMORY: name = "GPU Memory"; break;
+            case NvThermalTarget.POWER_SUPPLY: name = "GPU Power Supply"; break;
+            case NvThermalTarget.UNKNOWN: name = "GPU Unknown"; break;
+            default: name = "GPU"; break;
+          }
+          temperatures[i] = new Sensor(name, i, sensor.DefaultMaxTemp, 
+            SensorType.Temperature, this);
+        }
+      } catch (Exception e) {
+        System.Windows.Forms.MessageBox.Show(e.Message + "\n" + e.StackTrace);
+      }
+    }
+
+    public string Name {
+      get { return name; }
+    }
+
+    public string Identifier {
+      get { return "/nvidiagpu/" + adapterIndex; }
+    }
+
+    public Image Icon {
+      get { return icon; }
+    }
+
+    public ISensor[] Sensors {
+      get {
+        return temperatures;
+      }
+    }
+
+    public string GetReport() {
+      return null;
+    }
+
+    private NvGPUThermalSettings GetThermalSettings() {
+      NvGPUThermalSettings settings = new NvGPUThermalSettings();
+      settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
+      settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
+      settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
+      NVAPI.NvAPI_GPU_GetThermalSettings(handle, (int)NvThermalTarget.ALL,
+        ref settings);
+      return settings;
+    }
+
+    public void Update() {
+      NvGPUThermalSettings settings = GetThermalSettings();
+      foreach (Sensor sensor in temperatures) 
+        sensor.Value = settings.Sensor[sensor.Index].CurrentTemp;              
+    }
+
+    #pragma warning disable 67
+    public event SensorEventHandler SensorAdded;
+    public event SensorEventHandler SensorRemoved;
+    #pragma warning restore 67
+
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/Nvidia/NvidiaGroup.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/Nvidia/NvidiaGroup.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,74 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+
+namespace OpenHardwareMonitor.Hardware.Nvidia {
+
+  public class NvidiaGroup : IGroup {
+    private List<IHardware> hardware = new List<IHardware>();
+
+    public NvidiaGroup() {
+      if (!NVAPI.IsAvailable)
+        return;
+
+      NvPhysicalGpuHandle[] handles = 
+        new NvPhysicalGpuHandle[NVAPI.MAX_PHYSICAL_GPUS];
+  
+      int count;
+      if (NVAPI.NvAPI_EnumPhysicalGPUs(handles, out count) != NvStatus.OK)
+        return;
+
+      for (int i = 0; i < count; i++)         
+        hardware.Add(new NvidiaGPU(i, handles[i]));   
+    }
+
+    public IHardware[] Hardware {
+      get {
+        return hardware.ToArray();
+      }
+    }
+
+    public string GetReport() {
+      return null;
+    }
+
+    public void Close() {
+    }
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/ReportWriter.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/ReportWriter.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace OpenHardwareMonitor.Hardware {
+  public class ReportWriter {
+
+    private static void NewSection(TextWriter writer) {      
+      for (int i = 0; i < 8; i++)
+        writer.Write("----------");
+      writer.WriteLine();
+      writer.WriteLine();
+    }
+
+    public static void Save(List<IGroup> groupList, Version version) {
+
+      using (TextWriter w =
+        new StreamWriter("OpenHardwareMonitor.Report.txt")) {
+
+        w.WriteLine();
+        w.WriteLine("Open Hardware Monitor Report");
+        w.WriteLine();
+        NewSection(w);
+        w.Write("Version: "); w.WriteLine(version.ToString());
+        w.WriteLine();
+
+        foreach (IGroup group in groupList) {
+          string report = group.GetReport();
+          if (report != null) {
+            NewSection(w);
+            w.Write(report);            
+          }
+
+          IHardware[] hardwareArray = group.Hardware;
+          foreach (IHardware hardware in hardwareArray) {
+            string hardwareReport = hardware.GetReport();
+            if (hardwareReport != null) {
+              NewSection(w);
+              w.Write(hardwareReport);
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/SMBIOS/SMBIOSGroup.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/SMBIOS/SMBIOSGroup.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,198 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Management;
+using System.Text;
+
+namespace OpenHardwareMonitor.Hardware.SMBIOS {
+
+  public class SMBIOSGroup : IGroup {
+
+    private Structure[] table;
+
+    private BIOSInformation biosInformation = null;
+
+    private BaseBoardInformation baseBoardInformation = null;
+
+    public SMBIOSGroup() {
+      int p = (int)System.Environment.OSVersion.Platform;
+      if ((p == 4) || (p == 128))
+        return;
+          
+      ManagementObjectCollection collection = new ManagementObjectSearcher(
+         "root\\WMI", "SELECT SMBiosData FROM MSSMBios_RawSMBiosTables").Get();
+
+      byte[] raw = null;
+      foreach (ManagementObject mo in collection) {
+        raw = (byte[])mo["SMBiosData"];
+        break;
+      }
+
+      List<Structure> structureList = new List<Structure>();
+      if (raw != null && raw.Length > 0) {
+        int offset = 0;
+        byte type = raw[offset];
+        while (offset < raw.Length && type != 127) {
+          
+          type = raw[offset]; offset++;
+          int length = raw[offset]; offset++;
+          ushort handle = (ushort)((raw[offset] << 8) | raw[offset + 1]); 
+          offset += 2;
+          
+          byte[] data = new byte[length];
+          Array.Copy(raw, offset - 4, data, 0, length); offset += length - 4;
+
+          List<string> stringsList = new List<string>();
+          if (raw[offset] == 0)
+            offset++;
+          while (raw[offset] != 0) {   
+            StringBuilder sb = new StringBuilder();
+            while (raw[offset] != 0) {
+              sb.Append((char)raw[offset]); offset++;
+            }
+            offset++;
+            stringsList.Add(sb.ToString());
+          }
+          offset++;
+          switch (type) {
+            case 0x00:
+              this.biosInformation = new BIOSInformation(
+                type, handle, data, stringsList.ToArray());
+              structureList.Add(this.biosInformation); break;
+            case 0x02: this.baseBoardInformation = new BaseBoardInformation(
+                type, handle, data, stringsList.ToArray());
+              structureList.Add(this.baseBoardInformation); break;
+            default: structureList.Add(new Structure(
+              type, handle, data, stringsList.ToArray())); break;
+          }
+        }
+      }
+      table = structureList.ToArray();
+    }
+
+    public IHardware[] Hardware { get { return new IHardware[0]; } }
+
+    public string GetReport() {
+      StringBuilder r = new StringBuilder();
+
+      r.AppendLine("SMBIOS");
+      r.AppendLine();
+
+      if (biosInformation != null) {
+        r.Append("BIOS Vendor: "); r.AppendLine(biosInformation.Vendor);
+        r.Append("BIOS Version: "); r.AppendLine(biosInformation.Version);
+        r.AppendLine();
+      }
+
+      if (baseBoardInformation != null) {
+        r.Append("Mainboard Manufacturer: "); 
+        r.AppendLine(baseBoardInformation.Manufacturer);
+        r.Append("Mainboard Name: "); 
+        r.AppendLine(baseBoardInformation.ProductName);
+        r.AppendLine();
+      }
+     
+      return r.ToString();
+    }
+
+    public void Close() { }
+
+    public class Structure {
+      private byte type;
+      private ushort handle;
+
+      private byte[] data;
+      private string[] strings;
+
+      public Structure(byte type, ushort handle, byte[] data, string[] strings) 
+      {
+        this.type = type;
+        this.handle = handle;
+        this.data = data;
+        this.strings = strings;
+      }
+
+      public byte Type { get { return type; } }
+
+      public ushort Handle { get { return handle; } }
+    }
+
+    public class BIOSInformation : Structure {
+
+      private string vendor = "";
+      private string version = "";
+
+      public BIOSInformation(byte type, ushort handle, byte[] data,
+        string[] strings)
+        : base(type, handle, data, strings) {
+
+        if (data[0x04] > 0 && data[0x04] <= strings.Length)
+          vendor = strings[data[0x04] - 1];
+
+        if (data[0x05] > 0 && data[0x05] <= strings.Length)
+          version = strings[data[0x05] - 1];
+      }
+
+      public string Vendor { get { return vendor; } }
+
+      public string Version { get { return version; } }
+    }
+
+    public class BaseBoardInformation : Structure {
+
+      private string manufacturer  = "";
+      private string productName = "";
+
+      public BaseBoardInformation(byte type, ushort handle, byte[] data,
+        string[] strings)
+        : base(type, handle, data, strings) {
+
+        if (data[0x04] > 0 && data[0x04] <= strings.Length)
+          manufacturer = strings[data[0x04] - 1];
+
+        if (data[0x05] > 0 && data[0x05] <= strings.Length)
+          productName = strings[data[0x05] - 1];
+      }
+
+      public string Manufacturer { get { return manufacturer; } }
+
+      public string ProductName { get { return productName; } }
+    }
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/Sensor.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/Sensor.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,185 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+
+namespace OpenHardwareMonitor.Hardware {
+
+  public class Sensor : ISensor {
+
+    private string defaultName;
+    private string name;
+    private int index;
+    private SensorType sensorType;
+    private IHardware hardware;
+    private float? value;
+    private float? min;
+    private float? max;
+    private float? limit;
+    private float? defaultLimit;
+    private Queue<ISensorEntry> entries = 
+      new Queue<ISensorEntry>(MAX_MINUTES * 15);
+    
+    private float sum = 0;
+    private int count = 0;
+
+    private const int MAX_MINUTES = 120;
+
+    private string GetIdentifier() {
+      string s = "";
+      switch (sensorType) {
+        case SensorType.Voltage: s = "voltage"; break;
+        case SensorType.Clock: s = "clock"; break;
+        case SensorType.Temperature: s = "temperature"; break;
+        case SensorType.Fan: s = "fan"; break;
+      }
+      return hardware.Identifier + "/" + s + "/" + index;
+    }
+
+    public Sensor(string name, int index, SensorType sensorType,
+      IHardware hardware)
+      : this(name, index, null, sensorType, hardware) { }
+
+    public Sensor(string name, int index, float? limit, 
+      SensorType sensorType, IHardware hardware) 
+    {
+      this.defaultName = name;      
+      this.index = index;
+      this.defaultLimit = limit;
+      this.sensorType = sensorType;
+      this.hardware = hardware;
+      string configName = 
+        Utilities.Config.Settings[GetIdentifier() + "/name"];
+      if (configName != null)
+        this.name = configName;
+      else
+        this.name = name;
+      string configLimit =
+        Utilities.Config.Settings[GetIdentifier() + "/limit"];
+      if (configLimit != null && configLimit != "")
+        this.limit = float.Parse(configLimit);
+      else
+        this.limit = limit;
+    }
+
+    public SensorType SensorType {
+      get { return sensorType; }
+    }
+
+    public string Name {
+      get { 
+        return name; 
+      }
+      set {
+        if (value != "") 
+          name = value;          
+        else 
+          name = defaultName;
+        Utilities.Config.Settings[GetIdentifier() + "/name"] = name;
+      }
+    }
+
+    public int Index {
+      get { return index; }
+    }
+
+    public float? Value {
+      get { 
+        return value; 
+      }
+      set {
+        while (entries.Count > 0 && 
+          (DateTime.Now - entries.Peek().Time).TotalMinutes > MAX_MINUTES)
+          entries.Dequeue();
+
+        if (value.HasValue) {
+          sum += value.Value;
+          count++;
+          if (count == 4) {
+            entries.Enqueue(new Entry(sum / count, DateTime.Now));
+            sum = 0;
+            count = 0;
+          }
+        }
+
+        this.value = value;
+        if (min > value || !min.HasValue)
+          min = value;
+        if (max < value || !max.HasValue)
+          max = value;
+      }
+    }
+
+    public float? Min { get { return min; } }
+    public float? Max { get { return max; } }
+
+    public float? Limit {
+      get {
+        return limit;
+      }
+
+      set {
+        if (value.HasValue) {
+          limit = value;
+          Utilities.Config.Settings[GetIdentifier() + "/limit"] =
+            limit.ToString();
+        } else {
+          limit = defaultLimit;
+          Utilities.Config.Settings[GetIdentifier() + "/limit"] = "";          
+        }        
+      }
+    }
+
+    public IEnumerable<ISensorEntry> Plot {
+      get { return entries; }
+    }
+
+    public struct Entry : ISensorEntry {
+      private float value;
+      private DateTime time;
+
+      public Entry(float value, DateTime time) {
+        this.value = value;
+        this.time = time;
+      }
+
+      public float Value { get { return value; } }
+      public DateTime Time { get { return time; } }
+    }
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/TBalancer/TBalancer.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/TBalancer/TBalancer.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,198 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Drawing;
+using System.IO;
+using System.IO.Ports;
+using System.Text;
+
+namespace OpenHardwareMonitor.Hardware.TBalancer {
+  public class TBalancer : IHardware {
+
+    private Image icon;
+    private SerialPort serialPort;
+    private Sensor[] digitalTemperatures = new Sensor[8];
+    private Sensor[] analogTemperatures = new Sensor[4];
+    private Sensor[] fans = new Sensor[4];
+    private List<ISensor> active = new List<ISensor>();
+    private List<ISensor> deactivating = new List<ISensor>();
+    private int[] data;
+
+    public const byte STARTFLAG = 100;
+    public const byte PROTOCOL_VERSION = 0x2A;
+
+    public TBalancer(string portName) {
+      icon = Utilities.EmbeddedResources.GetImage("bigng.png");
+
+      try {
+        serialPort = new SerialPort(portName, 19200, Parity.None, 8,
+          StopBits.One);
+        serialPort.Open();
+        Update();
+      } catch (IOException) { }
+
+      for (int i = 0; i < digitalTemperatures.Length; i++) 
+        digitalTemperatures[i] = new Sensor("Digital Sensor #" + (i + 1), i, 
+          SensorType.Temperature, this);
+
+      for (int i = 0; i < analogTemperatures.Length; i++)
+        analogTemperatures[i] = new Sensor("Analog Sensor #" + (i + 1),
+          i + digitalTemperatures.Length, SensorType.Temperature, this);        
+    }
+
+    private void ActivateSensor(Sensor sensor) {
+      deactivating.Remove(sensor);
+      if (!active.Contains(sensor)) {
+        active.Add(sensor);
+        SensorAdded(sensor);
+      }      
+    }
+
+    private void DeactivateSensor(Sensor sensor) {
+      if (deactivating.Contains(sensor)) {
+        active.Remove(sensor);
+        deactivating.Remove(sensor);
+        SensorRemoved(sensor);
+      } else if (active.Contains(sensor)) {
+        deactivating.Add(sensor);
+      }     
+    }
+
+    private void ReadData() {
+      int[] data = new int[285];
+      for (int i = 0; i < data.Length; i++)
+        data[i] = serialPort.ReadByte();
+
+      if (data[0] != STARTFLAG || data[274] != PROTOCOL_VERSION) {
+        serialPort.DiscardInBuffer();   
+        return;
+      }
+
+      for (int i = 0; i < digitalTemperatures.Length; i++)
+        if (data[238 + i] > 0) {
+          digitalTemperatures[i].Value = 0.5f * data[238 + i];
+          ActivateSensor(digitalTemperatures[i]);
+        } else {
+          DeactivateSensor(digitalTemperatures[i]);
+        }
+
+      for (int i = 0; i < analogTemperatures.Length; i++)
+        if (data[260 + i] > 0) {
+          analogTemperatures[i].Value = 0.5f * data[260 + i];
+          ActivateSensor(analogTemperatures[i]);
+        } else {
+          DeactivateSensor(analogTemperatures[i]);
+        }
+      
+      for (int i = 0; i < fans.Length; i++) {
+        float maxRPM = 11.5f * ((data[149 + 2 * i] << 8) | data[148 + 2 * i]);
+        
+        if (fans[i] == null) 
+          fans[i] = new Sensor("Fan #" + (i + 1), i, maxRPM, SensorType.Fan, 
+            this);
+
+        if ((data[136] & (1 << i)) == 0)
+          fans[i].Value = maxRPM * 0.01f * data[156 + i]; // pwm mode
+        else
+          fans[i].Value = maxRPM * 0.01f * data[141 + i]; // analog mode
+        ActivateSensor(fans[i]);
+      }
+      this.data = data;
+    }
+
+    public Image Icon {
+      get { return icon; }
+    }
+
+    public string Name {
+      get { return "T-Balancer bigNG"; }
+    }
+
+    public string Identifier {
+      get { return "/bigng/" + 
+        serialPort.PortName.TrimStart(new char[]{'/'}).ToLower(); }
+    }
+
+    public ISensor[] Sensors {
+      get { return active.ToArray(); }
+    }
+
+    public string GetReport() {
+      StringBuilder r = new StringBuilder();
+
+      r.AppendLine("T-Balancer bigNG");
+      r.AppendLine();
+      r.Append("Port Name: "); r.AppendLine(serialPort.PortName);
+      r.AppendLine();
+      r.AppendLine("System Information Answer");
+      r.AppendLine();
+
+      r.AppendLine("       00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
+      r.AppendLine();
+      for (int i = 0; i <= 0x11; i++) {
+        r.Append(" "); r.Append((i << 4).ToString("X3")); r.Append("  ");
+        for (int j = 0; j <= 0xF; j++) {
+          int index = ((i << 4) | j);
+          if (index < data.Length) {
+            r.Append(" ");
+            r.Append(data[index].ToString("X2"));
+          }          
+        }
+        r.AppendLine();
+      }
+      r.AppendLine();
+
+      return r.ToString();
+    }
+
+    public void Update() {
+      while (serialPort.BytesToRead >= 285)
+        ReadData();
+      serialPort.Write(new byte[] { 0x38 }, 0, 1);
+    }
+
+    public void Close() {
+      serialPort.Close();
+    }
+
+    public event SensorEventHandler SensorAdded;
+    public event SensorEventHandler SensorRemoved;
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/TBalancer/TBalancerGroup.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/TBalancer/TBalancerGroup.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,112 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Ports;
+using System.Threading;
+
+namespace OpenHardwareMonitor.Hardware.TBalancer {
+  public class TBalancerGroup : IGroup {
+
+    private List<TBalancer> hardware = new List<TBalancer>();
+
+    public TBalancerGroup() {
+
+      string[] portNames = SerialPort.GetPortNames();
+      for (int i = portNames.Length - 1; i >= 0; i--) {
+        try {
+          SerialPort serialPort =
+            new SerialPort(portNames[i], 19200, Parity.None, 8, StopBits.One);
+          serialPort.Open();
+          bool isValid = false;
+          if (serialPort.IsOpen && serialPort.CDHolding &&
+            serialPort.CtsHolding) {
+            serialPort.DiscardInBuffer();
+            serialPort.DiscardOutBuffer();
+            serialPort.Write(new byte[] { 0x38 }, 0, 1);
+            int j = 0;
+            while (serialPort.BytesToRead == 0 && j < 2) {
+              Thread.Sleep(100);
+              j++;
+            }
+            if (serialPort.BytesToRead > 0 && 
+              serialPort.ReadByte() == TBalancer.STARTFLAG) 
+            {
+              while (serialPort.BytesToRead < 284 && j < 5) {
+                Thread.Sleep(100);
+                j++;
+              }
+              if (serialPort.BytesToRead == 284) {
+                int[] data = new int[285];
+                data[0] = TBalancer.STARTFLAG;
+                for (int k = 1; k < data.Length; k++)
+                  data[k] = serialPort.ReadByte();
+                
+                // check protocol version
+                isValid = (data[274] == TBalancer.PROTOCOL_VERSION); 
+              }
+            }
+          }
+          serialPort.DiscardInBuffer();
+          serialPort.Close();
+          if (isValid) {
+            hardware.Add(new TBalancer(portNames[i]));
+            return;
+          }
+        } catch (IOException) { } catch (UnauthorizedAccessException) { } 
+          catch (NullReferenceException) { }
+      }
+    }
+
+    public IHardware[] Hardware {
+      get {
+        return hardware.ToArray();
+      }
+    }
+
+    public string GetReport() {
+      return null;
+    }
+
+    public void Close() {
+      foreach (TBalancer tbalancer in hardware)
+        tbalancer.Close();
+    }
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Hardware/WinRing0.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Hardware/WinRing0.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,149 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace OpenHardwareMonitor.Hardware {
+
+  public class WinRing0 {
+    
+    public enum OlsDllStatus{
+      OLS_DLL_NO_ERROR                        = 0,
+      OLS_DLL_UNSUPPORTED_PLATFORM            = 1,
+      OLS_DLL_DRIVER_NOT_LOADED               = 2,
+      OLS_DLL_DRIVER_NOT_FOUND                = 3,
+      OLS_DLL_DRIVER_UNLOADED                 = 4,
+      OLS_DLL_DRIVER_NOT_LOADED_ON_NETWORK    = 5,
+      OLS_DLL_UNKNOWN_ERROR                   = 9
+    }
+
+    private static bool available = false;
+
+    private static string GetDllName() {   
+      int p = (int)System.Environment.OSVersion.Platform;
+      if ((p == 4) || (p == 128)) {
+        if (IntPtr.Size == 4) {
+          return "libring0.so";
+        } else {
+          return "libring0x64.so";
+        }
+      } else {
+        if (IntPtr.Size == 4) {
+          return "WinRing0.dll";
+        } else {
+          return "WinRing0x64.dll";
+        }
+      }                       
+    }
+    
+    private delegate bool InitializeOlsDelegate();
+    private delegate void DeinitializeOlsDelegate();
+    
+    public delegate uint GetDllStatusDelegate();
+    public delegate bool IsCpuidDelegate();
+    public delegate bool CpuidDelegate(uint index, out uint eax, out uint ebx, 
+      out uint ecx, out uint edx);
+    public delegate bool RdmsrPxDelegate(uint index, ref uint eax, ref uint edx, 
+      UIntPtr processAffinityMask);
+    public delegate byte ReadIoPortByteDelegate(ushort port);
+    public delegate void WriteIoPortByteDelegate(ushort port, byte value);
+    public delegate void SetPciMaxBusIndexDelegate(byte max);
+    public delegate uint FindPciDeviceByIdDelegate(ushort vendorId, 
+      ushort deviceId, byte index);
+    public delegate bool ReadPciConfigDwordExDelegate(uint pciAddress, 
+      uint regAddress, out uint value);
+
+    private static InitializeOlsDelegate InitializeOls;
+    private static DeinitializeOlsDelegate DeinitializeOls;
+
+    public static GetDllStatusDelegate GetDllStatus;
+    public static IsCpuidDelegate IsCpuid;
+    public static CpuidDelegate Cpuid;
+    public static RdmsrPxDelegate RdmsrPx;
+    public static ReadIoPortByteDelegate ReadIoPortByte;
+    public static WriteIoPortByteDelegate WriteIoPortByte;
+    public static SetPciMaxBusIndexDelegate SetPciMaxBusIndex;
+    public static FindPciDeviceByIdDelegate FindPciDeviceById;
+    public static ReadPciConfigDwordExDelegate ReadPciConfigDwordEx;
+
+    private static void GetDelegate<T>(string entryPoint, out T newDelegate) 
+      where T : class 
+    {
+      DllImportAttribute attribute = new DllImportAttribute(GetDllName());
+      attribute.CallingConvention = CallingConvention.Winapi;
+      attribute.PreserveSig = true;
+      attribute.EntryPoint = entryPoint;
+      attribute.CharSet = CharSet.Auto;
+      PInvokeDelegateFactory.CreateDelegate(attribute, out newDelegate);
+    }
+
+    static WinRing0() {
+      GetDelegate("InitializeOls", out InitializeOls);
+      GetDelegate("DeinitializeOls", out DeinitializeOls);
+      GetDelegate("GetDllStatus", out GetDllStatus);
+      GetDelegate("IsCpuid", out IsCpuid);
+      GetDelegate("Cpuid", out Cpuid);
+      GetDelegate("RdmsrPx", out  RdmsrPx);
+      GetDelegate("ReadIoPortByte", out ReadIoPortByte);
+      GetDelegate("WriteIoPortByte", out WriteIoPortByte);
+      GetDelegate("SetPciMaxBusIndex", out SetPciMaxBusIndex);
+      GetDelegate("FindPciDeviceById", out FindPciDeviceById);
+      GetDelegate("ReadPciConfigDwordEx", out ReadPciConfigDwordEx);
+
+      try {
+        if (InitializeOls != null && InitializeOls())
+          available = true;
+      } catch (DllNotFoundException) { }       
+    }
+    
+    public static bool IsAvailable {
+      get { return available; }
+    }
+
+    private static Deinitializer deinitializer = new Deinitializer();
+    private class Deinitializer {
+      ~Deinitializer() {
+        if (available)
+          DeinitializeOls();
+      }
+    }
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Licenses/Aga.Controls.License.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Licenses/Aga.Controls.License.txt	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,25 @@
+The BSD License
+
+Copyright (c) 2009, Andrey Gliznetsov (a.gliznetsov@gmail.com)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided 
+that the following conditions are met
+
+- Redistributions of source code must retain the above copyright notice, this list of conditions 
+and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice, this list of conditions 
+and the following disclaimer in the documentation andor other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff -r 77e062628ef5 -r 361e324a0ed4 Licenses/OpenHardwareMonitor.License.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Licenses/OpenHardwareMonitor.License.txt	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,470 @@
+                          MOZILLA PUBLIC LICENSE
+                                Version 1.1
+
+                              ---------------
+
+1. Definitions.
+
+     1.0.1. "Commercial Use" means distribution or otherwise making the
+     Covered Code available to a third party.
+
+     1.1. "Contributor" means each entity that creates or contributes to
+     the creation of Modifications.
+
+     1.2. "Contributor Version" means the combination of the Original
+     Code, prior Modifications used by a Contributor, and the Modifications
+     made by that particular Contributor.
+
+     1.3. "Covered Code" means the Original Code or Modifications or the
+     combination of the Original Code and Modifications, in each case
+     including portions thereof.
+
+     1.4. "Electronic Distribution Mechanism" means a mechanism generally
+     accepted in the software development community for the electronic
+     transfer of data.
+
+     1.5. "Executable" means Covered Code in any form other than Source
+     Code.
+
+     1.6. "Initial Developer" means the individual or entity identified
+     as the Initial Developer in the Source Code notice required by Exhibit
+     A.
+
+     1.7. "Larger Work" means a work which combines Covered Code or
+     portions thereof with code not governed by the terms of this License.
+
+     1.8. "License" means this document.
+
+     1.8.1. "Licensable" means having the right to grant, to the maximum
+     extent possible, whether at the time of the initial grant or
+     subsequently acquired, any and all of the rights conveyed herein.
+
+     1.9. "Modifications" means any addition to or deletion from the
+     substance or structure of either the Original Code or any previous
+     Modifications. When Covered Code is released as a series of files, a
+     Modification is:
+          A. Any addition to or deletion from the contents of a file
+          containing Original Code or previous Modifications.
+
+          B. Any new file that contains any part of the Original Code or
+          previous Modifications.
+
+     1.10. "Original Code" means Source Code of computer software code
+     which is described in the Source Code notice required by Exhibit A as
+     Original Code, and which, at the time of its release under this
+     License is not already Covered Code governed by this License.
+
+     1.10.1. "Patent Claims" means any patent claim(s), now owned or
+     hereafter acquired, including without limitation,  method, process,
+     and apparatus claims, in any patent Licensable by grantor.
+
+     1.11. "Source Code" means the preferred form of the Covered Code for
+     making modifications to it, including all modules it contains, plus
+     any associated interface definition files, scripts used to control
+     compilation and installation of an Executable, or source code
+     differential comparisons against either the Original Code or another
+     well known, available Covered Code of the Contributor's choice. The
+     Source Code can be in a compressed or archival form, provided the
+     appropriate decompression or de-archiving software is widely available
+     for no charge.
+
+     1.12. "You" (or "Your")  means an individual or a legal entity
+     exercising rights under, and complying with all of the terms of, this
+     License or a future version of this License issued under Section 6.1.
+     For legal entities, "You" includes any entity which controls, is
+     controlled by, or is under common control with You. For purposes of
+     this definition, "control" means (a) the power, direct or indirect,
+     to cause the direction or management of such entity, whether by
+     contract or otherwise, or (b) ownership of more than fifty percent
+     (50%) of the outstanding shares or beneficial ownership of such
+     entity.
+
+2. Source Code License.
+
+     2.1. The Initial Developer Grant.
+     The Initial Developer hereby grants You a world-wide, royalty-free,
+     non-exclusive license, subject to third party intellectual property
+     claims:
+          (a)  under intellectual property rights (other than patent or
+          trademark) Licensable by Initial Developer to use, reproduce,
+          modify, display, perform, sublicense and distribute the Original
+          Code (or portions thereof) with or without Modifications, and/or
+          as part of a Larger Work; and
+
+          (b) under Patents Claims infringed by the making, using or
+          selling of Original Code, to make, have made, use, practice,
+          sell, and offer for sale, and/or otherwise dispose of the
+          Original Code (or portions thereof).
+
+          (c) the licenses granted in this Section 2.1(a) and (b) are
+          effective on the date Initial Developer first distributes
+          Original Code under the terms of this License.
+
+          (d) Notwithstanding Section 2.1(b) above, no patent license is
+          granted: 1) for code that You delete from the Original Code; 2)
+          separate from the Original Code;  or 3) for infringements caused
+          by: i) the modification of the Original Code or ii) the
+          combination of the Original Code with other software or devices.
+
+     2.2. Contributor Grant.
+     Subject to third party intellectual property claims, each Contributor
+     hereby grants You a world-wide, royalty-free, non-exclusive license
+
+          (a)  under intellectual property rights (other than patent or
+          trademark) Licensable by Contributor, to use, reproduce, modify,
+          display, perform, sublicense and distribute the Modifications
+          created by such Contributor (or portions thereof) either on an
+          unmodified basis, with other Modifications, as Covered Code
+          and/or as part of a Larger Work; and
+
+          (b) under Patent Claims infringed by the making, using, or
+          selling of  Modifications made by that Contributor either alone
+          and/or in combination with its Contributor Version (or portions
+          of such combination), to make, use, sell, offer for sale, have
+          made, and/or otherwise dispose of: 1) Modifications made by that
+          Contributor (or portions thereof); and 2) the combination of
+          Modifications made by that Contributor with its Contributor
+          Version (or portions of such combination).
+
+          (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+          effective on the date Contributor first makes Commercial Use of
+          the Covered Code.
+
+          (d)    Notwithstanding Section 2.2(b) above, no patent license is
+          granted: 1) for any code that Contributor has deleted from the
+          Contributor Version; 2)  separate from the Contributor Version;
+          3)  for infringements caused by: i) third party modifications of
+          Contributor Version or ii)  the combination of Modifications made
+          by that Contributor with other software  (except as part of the
+          Contributor Version) or other devices; or 4) under Patent Claims
+          infringed by Covered Code in the absence of Modifications made by
+          that Contributor.
+
+3. Distribution Obligations.
+
+     3.1. Application of License.
+     The Modifications which You create or to which You contribute are
+     governed by the terms of this License, including without limitation
+     Section 2.2. The Source Code version of Covered Code may be
+     distributed only under the terms of this License or a future version
+     of this License released under Section 6.1, and You must include a
+     copy of this License with every copy of the Source Code You
+     distribute. You may not offer or impose any terms on any Source Code
+     version that alters or restricts the applicable version of this
+     License or the recipients' rights hereunder. However, You may include
+     an additional document offering the additional rights described in
+     Section 3.5.
+
+     3.2. Availability of Source Code.
+     Any Modification which You create or to which You contribute must be
+     made available in Source Code form under the terms of this License
+     either on the same media as an Executable version or via an accepted
+     Electronic Distribution Mechanism to anyone to whom you made an
+     Executable version available; and if made available via Electronic
+     Distribution Mechanism, must remain available for at least twelve (12)
+     months after the date it initially became available, or at least six
+     (6) months after a subsequent version of that particular Modification
+     has been made available to such recipients. You are responsible for
+     ensuring that the Source Code version remains available even if the
+     Electronic Distribution Mechanism is maintained by a third party.
+
+     3.3. Description of Modifications.
+     You must cause all Covered Code to which You contribute to contain a
+     file documenting the changes You made to create that Covered Code and
+     the date of any change. You must include a prominent statement that
+     the Modification is derived, directly or indirectly, from Original
+     Code provided by the Initial Developer and including the name of the
+     Initial Developer in (a) the Source Code, and (b) in any notice in an
+     Executable version or related documentation in which You describe the
+     origin or ownership of the Covered Code.
+
+     3.4. Intellectual Property Matters
+          (a) Third Party Claims.
+          If Contributor has knowledge that a license under a third party's
+          intellectual property rights is required to exercise the rights
+          granted by such Contributor under Sections 2.1 or 2.2,
+          Contributor must include a text file with the Source Code
+          distribution titled "LEGAL" which describes the claim and the
+          party making the claim in sufficient detail that a recipient will
+          know whom to contact. If Contributor obtains such knowledge after
+          the Modification is made available as described in Section 3.2,
+          Contributor shall promptly modify the LEGAL file in all copies
+          Contributor makes available thereafter and shall take other steps
+          (such as notifying appropriate mailing lists or newsgroups)
+          reasonably calculated to inform those who received the Covered
+          Code that new knowledge has been obtained.
+
+          (b) Contributor APIs.
+          If Contributor's Modifications include an application programming
+          interface and Contributor has knowledge of patent licenses which
+          are reasonably necessary to implement that API, Contributor must
+          also include this information in the LEGAL file.
+
+               (c)    Representations.
+          Contributor represents that, except as disclosed pursuant to
+          Section 3.4(a) above, Contributor believes that Contributor's
+          Modifications are Contributor's original creation(s) and/or
+          Contributor has sufficient rights to grant the rights conveyed by
+          this License.
+
+     3.5. Required Notices.
+     You must duplicate the notice in Exhibit A in each file of the Source
+     Code.  If it is not possible to put such notice in a particular Source
+     Code file due to its structure, then You must include such notice in a
+     location (such as a relevant directory) where a user would be likely
+     to look for such a notice.  If You created one or more Modification(s)
+     You may add your name as a Contributor to the notice described in
+     Exhibit A.  You must also duplicate this License in any documentation
+     for the Source Code where You describe recipients' rights or ownership
+     rights relating to Covered Code.  You may choose to offer, and to
+     charge a fee for, warranty, support, indemnity or liability
+     obligations to one or more recipients of Covered Code. However, You
+     may do so only on Your own behalf, and not on behalf of the Initial
+     Developer or any Contributor. You must make it absolutely clear than
+     any such warranty, support, indemnity or liability obligation is
+     offered by You alone, and You hereby agree to indemnify the Initial
+     Developer and every Contributor for any liability incurred by the
+     Initial Developer or such Contributor as a result of warranty,
+     support, indemnity or liability terms You offer.
+
+     3.6. Distribution of Executable Versions.
+     You may distribute Covered Code in Executable form only if the
+     requirements of Section 3.1-3.5 have been met for that Covered Code,
+     and if You include a notice stating that the Source Code version of
+     the Covered Code is available under the terms of this License,
+     including a description of how and where You have fulfilled the
+     obligations of Section 3.2. The notice must be conspicuously included
+     in any notice in an Executable version, related documentation or
+     collateral in which You describe recipients' rights relating to the
+     Covered Code. You may distribute the Executable version of Covered
+     Code or ownership rights under a license of Your choice, which may
+     contain terms different from this License, provided that You are in
+     compliance with the terms of this License and that the license for the
+     Executable version does not attempt to limit or alter the recipient's
+     rights in the Source Code version from the rights set forth in this
+     License. If You distribute the Executable version under a different
+     license You must make it absolutely clear that any terms which differ
+     from this License are offered by You alone, not by the Initial
+     Developer or any Contributor. You hereby agree to indemnify the
+     Initial Developer and every Contributor for any liability incurred by
+     the Initial Developer or such Contributor as a result of any such
+     terms You offer.
+
+     3.7. Larger Works.
+     You may create a Larger Work by combining Covered Code with other code
+     not governed by the terms of this License and distribute the Larger
+     Work as a single product. In such a case, You must make sure the
+     requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+     If it is impossible for You to comply with any of the terms of this
+     License with respect to some or all of the Covered Code due to
+     statute, judicial order, or regulation then You must: (a) comply with
+     the terms of this License to the maximum extent possible; and (b)
+     describe the limitations and the code they affect. Such description
+     must be included in the LEGAL file described in Section 3.4 and must
+     be included with all distributions of the Source Code. Except to the
+     extent prohibited by statute or regulation, such description must be
+     sufficiently detailed for a recipient of ordinary skill to be able to
+     understand it.
+
+5. Application of this License.
+
+     This License applies to code to which the Initial Developer has
+     attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+     6.1. New Versions.
+     Netscape Communications Corporation ("Netscape") may publish revised
+     and/or new versions of the License from time to time. Each version
+     will be given a distinguishing version number.
+
+     6.2. Effect of New Versions.
+     Once Covered Code has been published under a particular version of the
+     License, You may always continue to use it under the terms of that
+     version. You may also choose to use such Covered Code under the terms
+     of any subsequent version of the License published by Netscape. No one
+     other than Netscape has the right to modify the terms applicable to
+     Covered Code created under this License.
+
+     6.3. Derivative Works.
+     If You create or use a modified version of this License (which you may
+     only do in order to apply it to code which is not already Covered Code
+     governed by this License), You must (a) rename Your license so that
+     the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+     "MPL", "NPL" or any confusingly similar phrase do not appear in your
+     license (except to note that your license differs from this License)
+     and (b) otherwise make it clear that Your version of the license
+     contains terms which differ from the Mozilla Public License and
+     Netscape Public License. (Filling in the name of the Initial
+     Developer, Original Code or Contributor in the notice described in
+     Exhibit A shall not of themselves be deemed to be modifications of
+     this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+     COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+     WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+     DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+     THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+     IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+     YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+     COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+     OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+     ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+     8.1.  This License and the rights granted hereunder will terminate
+     automatically if You fail to comply with terms herein and fail to cure
+     such breach within 30 days of becoming aware of the breach. All
+     sublicenses to the Covered Code which are properly granted shall
+     survive any termination of this License. Provisions which, by their
+     nature, must remain in effect beyond the termination of this License
+     shall survive.
+
+     8.2.  If You initiate litigation by asserting a patent infringement
+     claim (excluding declatory judgment actions) against Initial Developer
+     or a Contributor (the Initial Developer or Contributor against whom
+     You file such action is referred to as "Participant")  alleging that:
+
+     (a)  such Participant's Contributor Version directly or indirectly
+     infringes any patent, then any and all rights granted by such
+     Participant to You under Sections 2.1 and/or 2.2 of this License
+     shall, upon 60 days notice from Participant terminate prospectively,
+     unless if within 60 days after receipt of notice You either: (i)
+     agree in writing to pay Participant a mutually agreeable reasonable
+     royalty for Your past and future use of Modifications made by such
+     Participant, or (ii) withdraw Your litigation claim with respect to
+     the Contributor Version against such Participant.  If within 60 days
+     of notice, a reasonable royalty and payment arrangement are not
+     mutually agreed upon in writing by the parties or the litigation claim
+     is not withdrawn, the rights granted by Participant to You under
+     Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+     the 60 day notice period specified above.
+
+     (b)  any software, hardware, or device, other than such Participant's
+     Contributor Version, directly or indirectly infringes any patent, then
+     any rights granted to You by such Participant under Sections 2.1(b)
+     and 2.2(b) are revoked effective as of the date You first made, used,
+     sold, distributed, or had made, Modifications made by that
+     Participant.
+
+     8.3.  If You assert a patent infringement claim against Participant
+     alleging that such Participant's Contributor Version directly or
+     indirectly infringes any patent where such claim is resolved (such as
+     by license or settlement) prior to the initiation of patent
+     infringement litigation, then the reasonable value of the licenses
+     granted by such Participant under Sections 2.1 or 2.2 shall be taken
+     into account in determining the amount or value of any payment or
+     license.
+
+     8.4.  In the event of termination under Sections 8.1 or 8.2 above,
+     all end user license agreements (excluding distributors and resellers)
+     which have been validly granted by You or any distributor hereunder
+     prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+     UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+     (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+     DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+     OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+     ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+     CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+     WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+     COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+     INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+     LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+     RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+     PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+     EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+     THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+     The Covered Code is a "commercial item," as that term is defined in
+     48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+     software" and "commercial computer software documentation," as such
+     terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+     C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+     all U.S. Government End Users acquire Covered Code with only those
+     rights set forth herein.
+
+11. MISCELLANEOUS.
+
+     This License represents the complete agreement concerning subject
+     matter hereof. If any provision of this License is held to be
+     unenforceable, such provision shall be reformed only to the extent
+     necessary to make it enforceable. This License shall be governed by
+     California law provisions (except to the extent applicable law, if
+     any, provides otherwise), excluding its conflict-of-law provisions.
+     With respect to disputes in which at least one party is a citizen of,
+     or an entity chartered or registered to do business in the United
+     States of America, any litigation relating to this License shall be
+     subject to the jurisdiction of the Federal Courts of the Northern
+     District of California, with venue lying in Santa Clara County,
+     California, with the losing party responsible for costs, including
+     without limitation, court costs and reasonable attorneys' fees and
+     expenses. The application of the United Nations Convention on
+     Contracts for the International Sale of Goods is expressly excluded.
+     Any law or regulation which provides that the language of a contract
+     shall be construed against the drafter shall not apply to this
+     License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+     As between Initial Developer and the Contributors, each party is
+     responsible for claims and damages arising, directly or indirectly,
+     out of its utilization of rights under this License and You agree to
+     work with Initial Developer and Contributors to distribute such
+     responsibility on an equitable basis. Nothing herein is intended or
+     shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+     Initial Developer may designate portions of the Covered Code as
+     "Multiple-Licensed".  "Multiple-Licensed" means that the Initial
+     Developer permits you to utilize portions of the Covered Code under
+     Your choice of the NPL or the alternative licenses, if any, specified
+     by the Initial Developer in the file described in Exhibit A.
+
+EXHIBIT A -Mozilla Public License.
+
+     ``The contents of this file are subject to the Mozilla Public License
+     Version 1.1 (the "License"); you may not use this file except in
+     compliance with the License. You may obtain a copy of the License at
+     http://www.mozilla.org/MPL/
+
+     Software distributed under the License is distributed on an "AS IS"
+     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+     License for the specific language governing rights and limitations
+     under the License.
+
+     The Original Code is ______________________________________.
+
+     The Initial Developer of the Original Code is ________________________.
+     Portions created by ______________________ are Copyright (C) ______
+     _______________________. All Rights Reserved.
+
+     Contributor(s): ______________________________________.
+
+     Alternatively, the contents of this file may be used under the terms
+     of the _____ license (the  "[___] License"), in which case the
+     provisions of [______] License are applicable instead of those
+     above.  If you wish to allow use of your version of this file only
+     under the terms of the [____] License and not to allow others to use
+     your version of this file under the MPL, indicate your decision by
+     deleting  the provisions above and replace  them with the notice and
+     other provisions required by the [___] License.  If you do not delete
+     the provisions above, a recipient may use your version of this file
+     under either the MPL or the [___] License."
+
+     [NOTE: The text of this Exhibit A may differ slightly from the text of
+     the notices in the Source Code files of the Original Code. You should
+     use the text of this Exhibit A rather than the text found in the
+     Original Code Source Code for Your Modifications.]
+
diff -r 77e062628ef5 -r 361e324a0ed4 Licenses/WinRing0.License.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Licenses/WinRing0.License.txt	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,21 @@
+Copyright (c) 2007-2009 OpenLibSys.org. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff -r 77e062628ef5 -r 361e324a0ed4 OpenHardwareMonitor.csproj
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OpenHardwareMonitor.csproj	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}</ProjectGuid>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <OutputType>WinExe</OutputType>
+    <NoStandardLibraries>false</NoStandardLibraries>
+    <AssemblyName>OpenHardwareMonitor</AssemblyName>
+    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <RootNamespace>OpenHardwareMonitor</RootNamespace>
+    <ApplicationIcon>Resources\icon.ico</ApplicationIcon>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>Bin\Debug\</OutputPath>
+    <DefineConstants>TRACE;DEBUG</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>none</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>Bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Merge|AnyCPU' ">
+    <OutputPath>bin\Merge\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <OutputType>Module</OutputType>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Aga.Controls, Version=1.7.0.0, Culture=neutral, PublicKeyToken=fcc90fbf924463a3, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>External\Aga.Controls.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Configuration" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Management" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="GUI\TypeNode.cs" />
+    <Compile Include="Hardware\CPU\AMD10CPU.cs" />
+    <Compile Include="Hardware\HDD\HDD.cs" />
+    <Compile Include="Hardware\HDD\HDDGroup.cs" />
+    <Compile Include="Hardware\HDD\SMART.cs" />
+    <Compile Include="Hardware\LPC\Chip.cs" />
+    <Compile Include="Hardware\SMBIOS\SMBIOSGroup.cs" />
+    <Compile Include="Hardware\LPC\W83627DHG.cs" />
+    <Compile Include="Hardware\ReportWriter.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="GUI\AboutBox.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="GUI\AboutBox.Designer.cs">
+      <DependentUpon>AboutBox.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Hardware\ATI\ADL.cs" />
+    <Compile Include="Hardware\ATI\ATIGroup.cs" />
+    <Compile Include="Hardware\ATI\ATIGPU.cs" />
+    <Compile Include="Utilities\Configuration.cs" />
+    <Compile Include="Utilities\CrashReport.cs" />
+    <Compile Include="Utilities\EmbeddedResources.cs" />
+    <Compile Include="GUI\HardwareNode.cs" />
+    <Compile Include="Hardware\IGroup.cs" />
+    <Compile Include="Hardware\IHardware.cs" />
+    <Compile Include="Hardware\ISensor.cs" />
+    <Compile Include="Hardware\LPC\IT87.cs" />
+    <Compile Include="Hardware\LPC\LPCGroup.cs" />
+    <Compile Include="GUI\MainForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="GUI\MainForm.Designer.cs">
+      <DependentUpon>MainForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Hardware\Nvidia\NVAPI.cs" />
+    <Compile Include="Hardware\Nvidia\NvidiaGPU.cs" />
+    <Compile Include="Hardware\Nvidia\NvidiaGroup.cs" />
+    <Compile Include="Utilities\PInvokeDelegateFactory.cs" />
+    <Compile Include="GUI\PlotPanel.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="GUI\PlotPanel.Designer.cs">
+      <DependentUpon>PlotPanel.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Program.cs" />
+    <Compile Include="Hardware\CPU\IntelCPU.cs" />
+    <Compile Include="Hardware\CPU\CPUGroup.cs" />
+    <Compile Include="Hardware\Sensor.cs" />
+    <Compile Include="GUI\SensorNode.cs" />
+    <Compile Include="Hardware\TBalancer\TBalancer.cs" />
+    <Compile Include="Hardware\TBalancer\TBalancerGroup.cs" />
+    <Compile Include="Hardware\WinRing0.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="GUI\AboutBox.resx">
+      <DependentUpon>AboutBox.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="GUI\MainForm.resx">
+      <DependentUpon>MainForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="GUI\PlotPanel.resx">
+      <DependentUpon>PlotPanel.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Resources\ati.png">
+    </EmbeddedResource>
+    <EmbeddedResource Include="Resources\bigng.png" />
+    <EmbeddedResource Include="Resources\clock.png" />
+    <EmbeddedResource Include="Resources\computer.png" />
+    <EmbeddedResource Include="Resources\cpu.png" />
+    <EmbeddedResource Include="Resources\fan.png" />
+    <EmbeddedResource Include="Resources\temperature.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Resources\chip.png" />
+    <EmbeddedResource Include="Resources\hdd.png" />
+    <Content Include="Resources\icon.ico" />
+    <EmbeddedResource Include="Resources\voltage.png" />
+    <EmbeddedResource Include="Resources\nvidia.png" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ProjectExtensions>
+    <VisualStudio AllowExistingFolder="true" />
+  </ProjectExtensions>
+  <PropertyGroup>
+    <PreBuildEvent>
+    </PreBuildEvent>
+    <PostBuildEvent>copy "$(ProjectDir)External\*.*" "$(TargetDir)"
+copy "$(ProjectDir)Licenses\*.*" "$(TargetDir)"</PostBuildEvent>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff -r 77e062628ef5 -r 361e324a0ed4 OpenHardwareMonitor.sln
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OpenHardwareMonitor.sln	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,41 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenHardwareMonitor", "OpenHardwareMonitor.csproj", "{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(MonoDevelopProperties) = preSolution
+		StartupItem = OpenHardwareMonitor.csproj
+		Policies = $0
+		$0.DotNetNamingPolicy = $1
+		$1.DirectoryNamespaceAssociation = None
+		$1.ResourceNamePolicy = FileFormatDefault
+		$0.TextStylePolicy = $2
+		$2.FileWidth = 120
+		$2.TabWidth = 2
+		$2.NoTabsAfterNonTabs = True
+		$2.inheritsSet = VisualStudio
+		$2.inheritsScope = text/plain
+		$2.scope = text/plain
+		$0.TextStylePolicy = $3
+		$3.inheritsSet = null
+		$3.scope = text/x-csharp
+		$0.CSharpFormattingPolicy = $4
+		$4.inheritsSet = Mono
+		$4.inheritsScope = text/x-csharp
+		$4.scope = text/x-csharp
+	EndGlobalSection
+EndGlobal
diff -r 77e062628ef5 -r 361e324a0ed4 Program.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Program.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,62 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Windows.Forms;
+
+
+namespace OpenHardwareMonitor {
+  static class Program {
+    /// <summary>
+    /// The main entry point for the application.
+    /// </summary>
+    [STAThread]
+    static void Main() {
+      #if !DEBUG
+      try {
+      #endif
+        Application.EnableVisualStyles();
+        Application.SetCompatibleTextRenderingDefault(false);
+        Application.Run(new GUI.MainForm());
+      #if !DEBUG
+      } catch (Exception e) {
+        Utilities.CrashReport.Save(e);
+      }
+      #endif
+    }
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Properties/AssemblyInfo.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Properties/AssemblyInfo.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Open Hardware Monitor")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Open Hardware Monitor")]
+[assembly: AssemblyCopyright("Copyright © 2009-2010 Michael Möller")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("f7a1c873-0bec-4762-8707-2edce3a6444d")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("0.1.0.0")]
+[assembly: AssemblyFileVersion("0.1.0.0")]
diff -r 77e062628ef5 -r 361e324a0ed4 Resources/ati.png
Binary file Resources/ati.png has changed
diff -r 77e062628ef5 -r 361e324a0ed4 Resources/bigng.png
Binary file Resources/bigng.png has changed
diff -r 77e062628ef5 -r 361e324a0ed4 Resources/chip.png
Binary file Resources/chip.png has changed
diff -r 77e062628ef5 -r 361e324a0ed4 Resources/clock.png
Binary file Resources/clock.png has changed
diff -r 77e062628ef5 -r 361e324a0ed4 Resources/computer.png
Binary file Resources/computer.png has changed
diff -r 77e062628ef5 -r 361e324a0ed4 Resources/cpu.png
Binary file Resources/cpu.png has changed
diff -r 77e062628ef5 -r 361e324a0ed4 Resources/fan.png
Binary file Resources/fan.png has changed
diff -r 77e062628ef5 -r 361e324a0ed4 Resources/hdd.png
Binary file Resources/hdd.png has changed
diff -r 77e062628ef5 -r 361e324a0ed4 Resources/icon.ico
Binary file Resources/icon.ico has changed
diff -r 77e062628ef5 -r 361e324a0ed4 Resources/icon.xcf
Binary file Resources/icon.xcf has changed
diff -r 77e062628ef5 -r 361e324a0ed4 Resources/nvidia.png
Binary file Resources/nvidia.png has changed
diff -r 77e062628ef5 -r 361e324a0ed4 Resources/temperature.png
Binary file Resources/temperature.png has changed
diff -r 77e062628ef5 -r 361e324a0ed4 Resources/voltage.png
Binary file Resources/voltage.png has changed
diff -r 77e062628ef5 -r 361e324a0ed4 Utilities/Configuration.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/Configuration.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,133 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace OpenHardwareMonitor.Utilities {
+
+  public sealed class Config {
+    private static readonly Config instance = new Config();
+
+    private string fileName;
+
+    private System.Configuration.Configuration config;
+
+    private Config() {
+      this.fileName = Path.ChangeExtension(
+        System.Windows.Forms.Application.ExecutablePath, ".config");
+      System.Configuration.ExeConfigurationFileMap fileMap = 
+        new System.Configuration.ExeConfigurationFileMap();
+      fileMap.ExeConfigFilename = fileName;        
+      config = System.Configuration.ConfigurationManager.
+        OpenMappedExeConfiguration(fileMap, 
+        System.Configuration.ConfigurationUserLevel.None);
+    }
+
+    ~Config() {
+      string tempName = Path.ChangeExtension(fileName, ".tmp");
+
+      if (File.Exists(tempName))
+        File.Delete(tempName);
+      try {
+        config.SaveAs(tempName);
+        if (File.Exists(fileName) && File.Exists(tempName))
+          File.Delete(fileName);
+        File.Move(tempName, fileName);
+      } catch (System.Configuration.ConfigurationErrorsException) { }
+    }
+
+    public static Config Settings {
+      get {
+        return instance;
+      }
+    }
+
+    public string this[string name] {
+      get {
+        System.Configuration.KeyValueConfigurationElement element =
+          config.AppSettings.Settings[name];
+        if (element != null)
+          return element.Value;
+        else
+          return null;
+      }
+      set {
+        config.AppSettings.Settings.Remove(name);
+        config.AppSettings.Settings.Add(name, value);
+      }
+    }
+
+    public static bool Contains(string name) {
+      System.Configuration.KeyValueConfigurationElement element =
+        instance.config.AppSettings.Settings[name];
+      return element != null;
+    }
+
+    public static void Set(string name, bool value) {
+      instance[name] = value ? "true" : "false";
+    }
+
+    public static bool Get(string name, bool value) {
+      System.Configuration.KeyValueConfigurationElement element =
+        instance.config.AppSettings.Settings[name];
+      if (element == null)
+        return value;
+      else
+        return element.Value == "true"; 
+    }
+
+    public static void Set(string name, int value) {
+      instance[name] = value.ToString();
+    }
+
+    public static int Get(string name, int value) {
+      System.Configuration.KeyValueConfigurationElement element =
+        instance.config.AppSettings.Settings[name];
+      if (element == null)
+        return value;
+      else {
+        int parsedValue;
+        if (int.TryParse(element.Value, out parsedValue))
+          return parsedValue;
+        else
+          return value;
+      }
+    }
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Utilities/CrashReport.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/CrashReport.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,58 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace OpenHardwareMonitor.Utilities {
+  public class CrashReport {
+
+    public static void Save(Exception e) {
+       using (TextWriter w =
+          new StreamWriter("OpenHardwareMonitor.Crash.txt")) {
+          w.WriteLine(e.ToString());
+          w.WriteLine();
+          if (e.InnerException != null) {
+            w.WriteLine(e.InnerException.ToString());
+            w.WriteLine();          
+          }
+        }
+    }
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Utilities/EmbeddedResources.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/EmbeddedResources.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,61 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Reflection;
+
+namespace OpenHardwareMonitor.Utilities {
+  public class EmbeddedResources {
+
+    public static Image GetImage(string name) {
+      name = "OpenHardwareMonitor.Resources." + name;
+
+      string[] names = 
+        Assembly.GetExecutingAssembly().GetManifestResourceNames();
+      for (int i = 0; i < names.Length; i++) {
+        if (names[i].Replace('\\', '.') == name)
+          return new Bitmap(Assembly.GetExecutingAssembly().
+        GetManifestResourceStream(names[i]));
+      }
+
+      return new Bitmap(1, 1);    
+    }
+         
+  }
+}
diff -r 77e062628ef5 -r 361e324a0ed4 Utilities/PInvokeDelegateFactory.cs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utilities/PInvokeDelegateFactory.cs	Tue Jan 26 22:37:48 2010 +0000
@@ -0,0 +1,118 @@
+/*
+  
+  Version: MPL 1.1/GPL 2.0/LGPL 2.1
+
+  The contents of this file are subject to the Mozilla Public License Version
+  1.1 (the "License"); you may not use this file except in compliance with
+  the License. You may obtain a copy of the License at
+ 
+  http://www.mozilla.org/MPL/
+
+  Software distributed under the License is distributed on an "AS IS" basis,
+  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  for the specific language governing rights and limitations under the License.
+
+  The Original Code is the Open Hardware Monitor code.
+
+  The Initial Developer of the Original Code is 
+  Michael Möller <m.moeller@gmx.ch>.
+  Portions created by the Initial Developer are Copyright (C) 2009-2010
+  the Initial Developer. All Rights Reserved.
+
+  Contributor(s):
+
+  Alternatively, the contents of this file may be used under the terms of
+  either the GNU General Public License Version 2 or later (the "GPL"), or
+  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  in which case the provisions of the GPL or the LGPL are applicable instead
+  of those above. If you wish to allow use of your version of this file only
+  under the terms of either the GPL or the LGPL, and not to allow others to
+  use your version of this file under the terms of the MPL, indicate your
+  decision by deleting the provisions above and replace them with the notice
+  and other provisions required by the GPL or the LGPL. If you do not delete
+  the provisions above, a recipient may use your version of this file under
+  the terms of any one of the MPL, the GPL or the LGPL.
+ 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.InteropServices;
+
+namespace OpenHardwareMonitor.Hardware {
+
+  public sealed class PInvokeDelegateFactory {
+
+    private static AssemblyBuilder assemblyBuilder;
+    private static ModuleBuilder moduleBuilder;
+
+    private static IDictionary<DllImportAttribute, Type> wrapperTypes =
+      new Dictionary<DllImportAttribute, Type>();
+
+    static PInvokeDelegateFactory() {
+
+      AssemblyName assemblyName = new AssemblyName();
+      assemblyName.Name = "PInvokeDelegateFactoryInternalAssembly";
+
+      assemblyBuilder =
+        AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
+        AssemblyBuilderAccess.Run);
+
+      moduleBuilder = assemblyBuilder.DefineDynamicModule(
+        "PInvokeDelegateFactoryInternalModule");
+    }
+
+    private PInvokeDelegateFactory() { }
+
+    public static void CreateDelegate<T>(DllImportAttribute dllImportAttribute,
+      out T newDelegate) where T : class 
+    {
+      Type wrapperType;
+      wrapperTypes.TryGetValue(dllImportAttribute, out wrapperType);
+
+      if (wrapperType == null) {
+        wrapperType = CreateWrapperType(typeof(T), dllImportAttribute);
+        wrapperTypes.Add(dllImportAttribute, wrapperType);
+      }
+
+      newDelegate = Delegate.CreateDelegate(typeof(T), wrapperType,
+        dllImportAttribute.EntryPoint) as T;
+    }
+
+
+    private static Type CreateWrapperType(Type delegateType,
+      DllImportAttribute dllImportAttribute) {
+
+      TypeBuilder typeBuilder = moduleBuilder.DefineType(
+        "PInvokeDelegateFactoryInternalWrapperType" + wrapperTypes.Count);
+
+      MethodInfo methodInfo = delegateType.GetMethod("Invoke");
+
+      ParameterInfo[] parameterInfos = methodInfo.GetParameters();
+      int parameterCount = parameterInfos.GetLength(0);
+
+      Type[] parameterTypes = new Type[parameterCount];
+      for (int i = 0; i < parameterCount; i++)
+        parameterTypes[i] = parameterInfos[i].ParameterType;
+
+      MethodBuilder methodBuilder = typeBuilder.DefinePInvokeMethod(
+        dllImportAttribute.EntryPoint, dllImportAttribute.Value,
+        MethodAttributes.Public | MethodAttributes.Static |
+        MethodAttributes.PinvokeImpl, CallingConventions.Standard,
+        methodInfo.ReturnType, parameterTypes,
+        dllImportAttribute.CallingConvention,
+        dllImportAttribute.CharSet);
+
+      foreach (ParameterInfo parameterInfo in parameterInfos)
+        methodBuilder.DefineParameter(parameterInfo.Position + 1,
+          parameterInfo.Attributes, parameterInfo.Name);
+
+      if (dllImportAttribute.PreserveSig)
+        methodBuilder.SetImplementationFlags(MethodImplAttributes.PreserveSig);
+
+      return typeBuilder.CreateType();
+    }
+  }
+}