From 39ca26510c4592c5459313b8dcd07b15b444b797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=B6ller?= Date: Tue, 26 Jan 2010 22:37:48 +0000 Subject: [PATCH] Initial commit. --- External/Aga.Controls.dll | Bin 0 -> 146432 bytes External/WinRing0.dll | Bin 0 -> 65536 bytes External/WinRing0.sys | Bin 0 -> 14416 bytes External/WinRing0.vxd | Bin 0 -> 8620 bytes External/WinRing0x64.dll | Bin 0 -> 57856 bytes External/WinRing0x64.sys | Bin 0 -> 14544 bytes GUI/AboutBox.Designer.cs | 214 ++++++++++ GUI/AboutBox.cs | 63 +++ GUI/AboutBox.resources | Bin 0 -> 4000 bytes GUI/AboutBox.resx | 185 ++++++++ GUI/HardwareNode.cs | 119 ++++++ GUI/LicenseBox.resources | Bin 0 -> 28675 bytes GUI/MainForm.Designer.cs | 523 +++++++++++++++++++++++ GUI/MainForm.cs | 325 ++++++++++++++ GUI/MainForm.resources | Bin 0 -> 15841 bytes GUI/MainForm.resx | 393 +++++++++++++++++ GUI/PlotPanel.Designer.cs | 79 ++++ GUI/PlotPanel.cs | 258 +++++++++++ GUI/PlotPanel.resources | Bin 0 -> 180 bytes GUI/PlotPanel.resx | 120 ++++++ GUI/SensorNode.cs | 121 ++++++ GUI/TypeNode.cs | 82 ++++ Hardware/ATI/ADL.cs | 251 +++++++++++ Hardware/ATI/ATIGPU.cs | 117 +++++ Hardware/ATI/ATIGroup.cs | 111 +++++ Hardware/CPU/AMD10CPU.cs | 113 +++++ Hardware/CPU/CPUGroup.cs | 208 +++++++++ Hardware/CPU/IntelCPU.cs | 151 +++++++ Hardware/HDD/HDD.cs | 110 +++++ Hardware/HDD/HDDGroup.cs | 101 +++++ Hardware/HDD/SMART.cs | 337 +++++++++++++++ Hardware/IGroup.cs | 52 +++ Hardware/IHardware.cs | 62 +++ Hardware/ISensor.cs | 66 +++ Hardware/LPC/Chip.cs | 17 + Hardware/LPC/IT87.cs | 225 ++++++++++ Hardware/LPC/LPCGroup.cs | 176 ++++++++ Hardware/LPC/W83627DHG.cs | 60 +++ Hardware/Nvidia/NVAPI.cs | 243 +++++++++++ Hardware/Nvidia/NvidiaGPU.cs | 126 ++++++ Hardware/Nvidia/NvidiaGroup.cs | 74 ++++ Hardware/ReportWriter.cs | 47 ++ Hardware/SMBIOS/SMBIOSGroup.cs | 198 +++++++++ Hardware/Sensor.cs | 185 ++++++++ Hardware/TBalancer/TBalancer.cs | 198 +++++++++ Hardware/TBalancer/TBalancerGroup.cs | 112 +++++ Hardware/WinRing0.cs | 149 +++++++ Licenses/Aga.Controls.License.txt | 25 ++ Licenses/OpenHardwareMonitor.License.txt | 470 ++++++++++++++++++++ Licenses/WinRing0.License.txt | 21 + OpenHardwareMonitor.csproj | 148 +++++++ OpenHardwareMonitor.sln | 41 ++ Program.cs | 62 +++ Properties/AssemblyInfo.cs | 36 ++ Resources/ati.png | Bin 0 -> 937 bytes Resources/bigng.png | Bin 0 -> 702 bytes Resources/chip.png | Bin 0 -> 852 bytes Resources/clock.png | Bin 0 -> 354 bytes Resources/computer.png | Bin 0 -> 576 bytes Resources/cpu.png | Bin 0 -> 611 bytes Resources/fan.png | Bin 0 -> 1107 bytes Resources/hdd.png | Bin 0 -> 649 bytes Resources/icon.ico | Bin 0 -> 15342 bytes Resources/icon.xcf | Bin 0 -> 44594 bytes Resources/nvidia.png | Bin 0 -> 944 bytes Resources/temperature.png | Bin 0 -> 721 bytes Resources/voltage.png | Bin 0 -> 639 bytes Utilities/Configuration.cs | 133 ++++++ Utilities/CrashReport.cs | 58 +++ Utilities/EmbeddedResources.cs | 61 +++ Utilities/PInvokeDelegateFactory.cs | 118 +++++ 71 files changed, 7144 insertions(+) create mode 100644 External/Aga.Controls.dll create mode 100644 External/WinRing0.dll create mode 100644 External/WinRing0.sys create mode 100644 External/WinRing0.vxd create mode 100644 External/WinRing0x64.dll create mode 100644 External/WinRing0x64.sys create mode 100644 GUI/AboutBox.Designer.cs create mode 100644 GUI/AboutBox.cs create mode 100644 GUI/AboutBox.resources create mode 100644 GUI/AboutBox.resx create mode 100644 GUI/HardwareNode.cs create mode 100644 GUI/LicenseBox.resources create mode 100644 GUI/MainForm.Designer.cs create mode 100644 GUI/MainForm.cs create mode 100644 GUI/MainForm.resources create mode 100644 GUI/MainForm.resx create mode 100644 GUI/PlotPanel.Designer.cs create mode 100644 GUI/PlotPanel.cs create mode 100644 GUI/PlotPanel.resources create mode 100644 GUI/PlotPanel.resx create mode 100644 GUI/SensorNode.cs create mode 100644 GUI/TypeNode.cs create mode 100644 Hardware/ATI/ADL.cs create mode 100644 Hardware/ATI/ATIGPU.cs create mode 100644 Hardware/ATI/ATIGroup.cs create mode 100644 Hardware/CPU/AMD10CPU.cs create mode 100644 Hardware/CPU/CPUGroup.cs create mode 100644 Hardware/CPU/IntelCPU.cs create mode 100644 Hardware/HDD/HDD.cs create mode 100644 Hardware/HDD/HDDGroup.cs create mode 100644 Hardware/HDD/SMART.cs create mode 100644 Hardware/IGroup.cs create mode 100644 Hardware/IHardware.cs create mode 100644 Hardware/ISensor.cs create mode 100644 Hardware/LPC/Chip.cs create mode 100644 Hardware/LPC/IT87.cs create mode 100644 Hardware/LPC/LPCGroup.cs create mode 100644 Hardware/LPC/W83627DHG.cs create mode 100644 Hardware/Nvidia/NVAPI.cs create mode 100644 Hardware/Nvidia/NvidiaGPU.cs create mode 100644 Hardware/Nvidia/NvidiaGroup.cs create mode 100644 Hardware/ReportWriter.cs create mode 100644 Hardware/SMBIOS/SMBIOSGroup.cs create mode 100644 Hardware/Sensor.cs create mode 100644 Hardware/TBalancer/TBalancer.cs create mode 100644 Hardware/TBalancer/TBalancerGroup.cs create mode 100644 Hardware/WinRing0.cs create mode 100644 Licenses/Aga.Controls.License.txt create mode 100644 Licenses/OpenHardwareMonitor.License.txt create mode 100644 Licenses/WinRing0.License.txt create mode 100644 OpenHardwareMonitor.csproj create mode 100644 OpenHardwareMonitor.sln create mode 100644 Program.cs create mode 100644 Properties/AssemblyInfo.cs create mode 100644 Resources/ati.png create mode 100644 Resources/bigng.png create mode 100644 Resources/chip.png create mode 100644 Resources/clock.png create mode 100644 Resources/computer.png create mode 100644 Resources/cpu.png create mode 100644 Resources/fan.png create mode 100644 Resources/hdd.png create mode 100644 Resources/icon.ico create mode 100644 Resources/icon.xcf create mode 100644 Resources/nvidia.png create mode 100644 Resources/temperature.png create mode 100644 Resources/voltage.png create mode 100644 Utilities/Configuration.cs create mode 100644 Utilities/CrashReport.cs create mode 100644 Utilities/EmbeddedResources.cs create mode 100644 Utilities/PInvokeDelegateFactory.cs diff --git a/External/Aga.Controls.dll b/External/Aga.Controls.dll new file mode 100644 index 0000000000000000000000000000000000000000..bf335bad00049bdd587348321a78028e595ba057 GIT binary patch literal 146432 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 XzolwW;oGz)T`yBY6{%EE3 literal 0 HcmV?d00001 diff --git a/External/WinRing0.dll b/External/WinRing0.dll new file mode 100644 index 0000000000000000000000000000000000000000..9ea86ea0be70da76db96e3eb19ed27a540251ad7 GIT binary patch literal 65536 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 literal 0 HcmV?d00001 diff --git a/External/WinRing0.sys b/External/WinRing0.sys new file mode 100644 index 0000000000000000000000000000000000000000..feaea414a8b4991a2de419dc0c81a9144256807b GIT binary patch literal 14416 zcmeHtc|6qH`}ljtU@$@`%34S&y~o%|wh`IKT1b|`WSKEDDp8EBrlG4%n@Ss%+oqCA zB`RrA+Gy8uLnL)8OESObJt(^ObMN=}{eD09^ZVm>yw05W^PJ~-&U4Ormh(Pu?(_2z zF$6&fP=!JSsel$MwxZv^{_(;i$QaEtV~`V4H?=EpZa1}kV;CGQ7MmH(4vW`{2uny{ za<#(gTI{3*Ek=TtqoqTuw=>}1oBWh`kh!~7_SY0nFg1F%%kaAst^DwR%!Q*6bL?m4n zLDD4$vDpgnj2WFA2IG))_{FNkP!)$3E9t6(bYna)Dy#sLJl4XGsQunxNaQNWwT3ob z2|=nb!yYP_oZA|JS3!_`z%7Jv)rLF&q)mr@+mU#H7mkE~dN$A!f}O9Fj-v@e(RK$_+m`!&CMbuB5+E*$W;Q)KwFZ z8(3LHjM10JA+1qhI+^r-1cV5Paz+Aoc|MNsO%PC3Y7ru+SxfC75DJBqs&-XMm2HiH z-U?lrTEqAXm}r$qNVU?SU`(>me$*cea z|Di4Azo#uGWLWSG(HioW6K^cEEfi2m0)%S~&~1RYI`D80dyo}S)nLjM;D}Z26j)z* zSW1Dr5+Bz-5g?^OC<;IlfGUIFDjaZO3KA(*A=N5_i!(f0Q_)ku4IY}Y z2g$*4^o1;fw@{e?(%L7;ow6l(0YtUK0ys@(76L9Vm$4cEN|oT2n0t?6b!HnbvkA$r zN?Vdj$Z+pG8OjO_D**tmeVTAF36{!7 zsB8>W?P}jaa}1RI4q5{k093ZnrZ1O6f?$!UDwrX_9=D5&W)TW5HtY$a-G&(whxc^y z@UqFn<_ghPS8y$XpNimW_rr;G-3^mLl61&0yNDZ1GP8%s8M29q0(X^6Z6vd*#|!p2 z&za~wD2D-ZM)Uc=LXred3-dhGfI+TYKJzUSZ~^wUN-paFZ1~){a#{J%X1*oKWn&0| z7wIf!>{fT>RyM-2%4MB`-?O<|gQy$;xQV7}fI|`eQVUJ^2Cz3#!sDMNG^0hcHGNernli)d0;+_{q1N8AN+C-VB7p-q}Sid4j13R`qR6kH}{&cc>M$Q>_~#U9$_h7l4%aSTBb z8r>1p^H-<{mG!|21+}3IfYxs))ee=yq!u3+9Uq}+{|A{iVKDKvp)MFfsI^87d*`8=r8 zntl8Ob|Ektnc7de?8T?Ig2xJ|{X?k-+&+)m6}boFs}Z<&Me<>(5M*8`OkMC>hEY0d!4|Y)S4;kB3T5IxMO1mXLna{wKZoD4Z)x9O!`@T-cRC}i-x!u`>zjS0V!ayRRU^%~T2sC%L2LtOz?8apRLF^A_#P{W~)h5BhMf;@m)0ks(F z8mNn*dO=?#vd|d55Eh67b3n;ufn+>t62H|k~9eZ-~Ga3YQbR=lS}h)^f}AX zOo`+xI31+L9lY~(J;XcE$1*sE$%R+)Mf3=6@DfG>n~@NW26LE6>b(! zd!Vmms9!|%ANcWjV|(_P>IKLDz|cR26gi40+GJOq#x#OhaxqCmpgbLXq5|`oi>*Wo zevin-Bn1~m58b!-U_KSncB=VSO_M&Kr4_Bdp7!*s*#zuO0NaV|_p zdK{fgccd?7M9>jr%6E)Ua(p;5juGL;NQi}0E=J?Vxg;>SehG{SxGD1CV&)2XynDP~ zLVOs@h3Ufz!z6U!X;eGMP#SfPi;pjr7HaS3nCK|cPAULR*qnlJLOJPVrujh>i9=Wr238?X*+dKi~JdIl4})ei+82_G9qFf zm`Mp-B!SE1#Ih6O4CzZ@7XFB67G9v$km`XWF@x$t^cz7XQW9bu&Bd1*I)V{dFbX%w z8ZrtuI6q~?IV^4took=OafGV~`()3kC=Q*A=wf)EKjNM3+zcU3AlI?I@k@XZ5{VS! zTZ(24qQ8=kCuhQ&Usj@{{vnM4%=7^Z3g=e#**PrC0NWD zF#d=SlM}RYkc(U(TSY-8Ly*lP8Wb^xj75eS7$f1LoHZ9w1zrcBiHAQr&~qWv zVfi5jAT7W#kw}mh1(gm@T5#p!19?sh1fT~Kf?@-XJuHibgn_JNm|2)eF4pgf zutX!c0cSW!Nd`_skk3ZIwV+rcQoui~JC;j1ka@8=u|O*ZP$r1ze$K)e5{0{!AH4p+ z%LeWrJY*Qj2r3E{J1|=!vOtfm4_8E+0D8ua(Dvss3_%*EFIILSvw+tP_@YHz*y^#M z7t=Hv)(zZJw4$SNT8KVir^3n^ffguYhRhgxG6&pWt&Jh{+ktj*(Eb>MBZ9Cs!sfad zej{OSSg{w)&2xwrJF#GM8(voo!gd<@!)a#Z9F0VK;RQ0V{ZE2@;Eq_GKk{PZ8jJQ| zG|$gF@$)`l2@eMz5e6d-Yxu)zA%B3qW7fz93e3{tpdD!o3WTE=!T(BOfs~ELJB<$* zpD?~`tZBkA5t_)Fs+le_U22+RT5YOtR%X^@)?)U>Y{1OTBFHk*GR`u|GRv~qvedG{ z^0DP>%eR(2mSR?lR+FqutY}tcR{7SitQBUd&r-ITYs0W%+AOzOZBseB3Ug+81ojW^ zh*4WK7+r{_qUorByo0=le2835K1YVGf3#qC(g+@ppcxwHB%};-oO8Nmagz9=42{Ep zI*7;N$TFyug!r^EV)zN-2pS_HJxu~fz-5@>afG7zXdp@%fssRX#c)WG)^3e-HMj=H z{yf3uIbcj!Si)S+2Kz&`N5~{76}huiH^gth>mBBGV(Ip_nRiuKM~X63!_f?}b7%&B zUy&FdhsVQ9FBF`znU3~;RQ9{FIB`%bLZqdbA3;J9Z%-wwqT?k1kXDqR6UPjPw8Dr^ z&`MZ5gA+y`hbm!RGK#XE;ni(@#_NQa& zy3WN&9%Y58bDsbD^vn4trejwGFHAm9kCdA}wmA5xPu;T3IOSEfE6?%rXB_f%bt64; zzqN8#gI|4J%Bx?mxy(E}X_B^VLVcF@(^%=*X+=|Mm+bJ{e>pdK-JYOQrEgz@m&F#= zPI&YBL0x}Gi~8Dx;%O0PohjYSb75wORxqSzUTHTzYa`WqAU(cg!gl_$^_19VAIT}J z>#N*LUP`a)5B(4@t~H|Nj`wHTHT)Un)oZJ$>zvb9(q?3Rif7|~yS1%}JTR^J;695q z%i7h;?th(9)SvrIvFc;`z`B9`_IKr6O4gqtMV=r&sHpyie>*4SObZ?i4!4KLL(@T)=oPy~00_E>!~K?NO`u5>5pcUL{veMehDzWJwp z`Cw@7;ZuZKU<{fBBNRmqi>4PDGb7k>hS4Hp;(#$3CeXPve^`eh^p4ym zFiF@Y9O4@1v7dO->-u52P1Q^EiX216*x)sqn~5m{L6uX-*if&TP-Yu!`nov!i-TVH z&ShH$W_GwA7*OhJ3bfmjaXOQ_)cNa!0}26*$8r98C+_s5)v{De{0_W-&O26+_q8uV z(35g!{_5vyaaL!{OuAxy8>ToJ-jl6~Jmls%wXT;jZK`l%04kj-YZ0o8W4{_J)U`@& zUA3U+;=sa7&e37%udhiRccmRxh{b)J<`|o?jGMb(x-)dm&M)i*>h<%Jv#JwL8HCN> z@sa(dyR6wJ-Z(1wh*#|T>+@&4m@kf5_oR&g1BAb#au%{?EE!h|)8<~;GA`nd!`J%}4HGg6kg$A!MHaCIJ=3oP< zqZ6@#WE7P!>3`_{i>QOeP~a3rr@wXSbMMg)=m+BieEJf1r;@z!hh-2CIMhP0GuU#_QU%_SnO*2D~rTVrteIRqUG|N|46SzJ=0rI=61LTeqg@kkqWZ z?Yp^$cB*Pgl`k(|V6xNGVv*R%)rT|-!ehsuE?v3sen|Yob#=ED58qq$&}+ZrTEfw{ zbKZuQy(3&~#HDKYTuPkWAL~YUq}1f8zqu2oMw{w%Nuou@q-!273gO=>e3i2FpwG+B zUrjc)d<$u`->~uSgaoqRoW}M;wQf6o6Ei1_zuMbUABg*8dg1Wwc{}N;wvxddE#uu| zYg|6X*fKQu&Dm|1r#3~LopaP8)(%o3Bcf94~Y!mCJMPl##xAr=k z(Z-?l+6Ir^a(So9%cIw{xOL=hJpZP?WYSXZuZ=z2Eyug-1&ZeP3vT2szC6>s%<^#9 zd6|`4UTKF%PPWL)`jVa3y+nA_T%v2mMd#3yoq>81QR0)h>oQ9opX^=ts~dl-*Nr0(yR|^&-Z*tK5}*4FB=jsH8@`OeXMa(M*4vLo+A$& zEYv%HS-&|j=zKz<%;$)X1zW0nefw~dPLE`dM(W&J(;%VlX}vpQ2{mYMW$4lLv*czO zUtI7wb+*TS1IC<&iBT&;aS0zx*2Xp)4jiR6jhk}vvY`5r54d^{xO($QSH}?_hN(UH zX|?{Xu5MugzHLs%!uKCtoyYqx2N_*-GS~okx|$c80m(R7YcSYrc_oF%F*q@BD}V(A zND>&CnBtTXq2sSO{?_+*Z%Z;LQ9L7+sH5_Hmqhr~u{)mZNaD0U_YYtcDEfPTyjqD1 ze5aSgmRa~&^|GH>z_!!!b-V6yZG~}2>l+`lfm4r?Z7OKyZM^9_$53d+H(B*_L&85b zL@%h^G*|Lk<d_?RuMIO(X2YSdLwxFLjfWy_SdW zlGyD;^4mB^>F!#moR}>wQ$B6z*lOq9U2tz%?hD6FF^OVLfy{F!zY5aFmRK>l<@+?L|VL4X~{IXv~kXnS806`;}J=2BlS4x^U{r+R_V@5 z&Fowag@YPr7u5HjKsq_+ZvHoYU)ei(LMmxq@1vVdmn;>x)-9cp=Kjz5ev!Rl#o`kC z#2j09C-)$|qer>Dv-$f|Qcr!jvZ*=4V#{`ifrS~S_9uf@=6w$NbXIsk-f@58-P#Y6 z>^^SYyRRdn@3(gPTvc?tptk(mli4rgzTKxON%qI<+&F%Nx4Vk=`;^o1J0xZ`?RUW& zF>1x_H{3q^>g)kx&3dnikF(;d&S=m!(+d?BpF4g(dg@Hgl!Mc~i@s%h>RCJQ;Y}$X z=uBI>rJ8zcyC!W#<3_=^7q_))j;!$BJu}LxbjGb2YjWL}t5|63e|>T|p3b}7+^FK( zah(u}Hvu@=SY|QuWshK1bxy z41yf^e)lNfmtWVOvGHf${|{u_!Be{t9N8^KMTH>{Ws())MlRY~p(IWqE-bt4_;@5l+-*7FHh{ z_uyRQM#;xGgRoa0|OJ@6II$R6AJN zR?3s};^M}=^r&AR-`$TY^j`i|QNe4!=P6&!jw4$pSQNd}7gI<%bF}PhmQ8sN*Ok9* zi}co(9=>}8zwX37gpyCcWWTV!(!t(b@&2=**xeotv*%h+qXTgjlYQQsNk-w)E<{U- z%d}h=3IPXDUh(MkFPT0f+aFQ)m2o}An3k(!?7$0=EiE;guZ7NrErZj$Icka;7a0|y zIfj3o?Xe@=@BvSh`4uq%x&#s`EkT6$Tyb$pG2*C~hCe-IjD8sv9S0(}NnZQ)hMk7l zd!}*W$<}Mmy^r4Zb&od;KBQ{JQRtZe_*;rLIjm}(chIq@qp6Wi1M(*l_gC&nGAj&a zetbkQtLUf_d+C2_>Aa1B>dR7XR2tok&h=`vOs1wiYtEx*1W~_5USZZWz8!0)PO@0= zrJ$$g<_=Av_bSHX&4M*2rmV`C@W6Um=~0hUHm&!J?_At#;bUFKO;I*OeT&;q>)e=0 zbajaQF!xAaVXJRk+2bcx$7&~K?ets2-e0!=OP5fruAsd%gY)P-)nC>0+nKn^#IC!w zHH#ZxSH9d;%tmgVD?{F`J7`fV)sSG}lVfnt%A2$KlyBRn8C#Zgjo+&B1RUf0i^hvVolQdmNH5);*ATJmbkv`ma%p@)3p3p{q?O=O>Awp2c`-SWo+)NxX-_4^7Q)6 z0Ez3{USHU-KYerPl7g=CmQrrAt#)xl+il6U=d#UD94`2Emr#lGXdku0J*VEl`u)A< z`eTv~>|do={W^8w`j5Id#IiQM@hIOpoI>=(T`|O2BIY9*2yG760QmeHI)7nWF0=QIz=kq5;8;iV=T$82OVJp>Qu`^`}{~ z+gEs&AcR-8vR;%mJgZ$5ug*`McEIU3f#w>w>ZpxtHD9?~%zZVHb;>c}iNtF6 zc-_{`W1mzOJa*g)f0{_db>Nyd<^}?p{6T!nyd0G7I%)%xTKi3sXoH4W!dKw<#Eb2=8DJH z%Y;j;diugKP5ywFj$q*v@$R5~N@XejY?*?$7y89n`Scy)YI~nb9&rtLcEuvv>M|G2 z5QjJ+7Cjgvq{C#=;1e7a)t^H|+K6+zpU-fo| ziY^gMQ4=Ey*$hQZ$k-*q5C~U+jrMWv^5*#aCg_?44xEp6ZTAy{Qgc*0Fs?-D+`#w9YAmdg%qh3&qMfRXi>M3m!69 zK#{|44RJYtb?NY@*8}R`2UUVgNR2V@{RjJ=!ht^r#BNlq2>&Xr9hByfpzuh_*DLn( zor1&W0oOaxQYpaU5}si61s*LpV&%WW_SDtI3)09~O~G5nRs9@3!m! z->*fM{QX+v=MV(*RJrQYkTs&TKROYTq*7X}wdx8r+ZH`(N z&X{5bF0;BIXMFp-Jx2^NoglmV^DrRXv+M1yC{t?2}KT{X_yL(8@BVC5B?_0;p znr%}lY7eXnG*|L2`!pI%q1-c6O(h1#KlV`Fa^P*~?_0O$dRxv9J~#6K(PW!%$zziV zv~d(;%RT9YMc+eGBuhsEq_Datj_jK99DKz`Dhc=t(Z+cyECt2Z@e6I6-G(?(2d-i$N z+q?-gqU%1TD`lO^CN)Iq@4Ld(2_t6^uE0^P8jr)F?0@8#Gx{^mk1tC_G*o`Xmn0Gy z4(YGvpA&MuE<(RcGF0Znl@>LN}Ax{e5>n;}g*;I2wVS2m1MTUiPaN^{kQ>JG=-RzNB z@!+*$Vdkz3{C#*;Z}_o#666egHK5L8Ho!~&4_t`jWkeqaaDz7nBTOO#Hx9m`ecxv> zvdnit5(nA+dyhC-PV_O(%m}XeDJTU}^3V2R;M~~siYm$OTJtgL)|nNqwnf@wQC_)( z%+NPaDS14J3~!vgJt(gT=q?-mDqqO6{Nnxu*=e=!+iKXk>}+I?qV_MMq|PwEhQ`)xqO; z?&x9P)SEZ;ojI!~O6qI(foV=hR<)ke*Ie|FOHw$vo3i+<>41ap9d_0JKHj>;-m&C~W{_`?lB`cc0(~szI*t1QdUc7d$!H(q?ya~Up%kA6{b$JXSZ0ZTdtCa_xawP zodAWVnza4nLwBF|zVG|}zVG+*eeZ?y`L|6l2V+dcT_`X%38ZVi`MmYx9ENXO^4e|e z)ylI=Cxw=?OS^W5W6Dr;a96Z85ryf)>l_o)!DAU zKWdzRBlV0{ytlpgUF|&jj?-h>IpCeA5+>64UvMuw{gT=52=ClYvYSQN;FTq9%>XgPa(2H6GW0%Y>yqp)v|Dh$K+3p^$lQ!AMt^h(V|SP% z3w!(!`jwV1@takajZa~WrX+tY8(X~xsbIJkDU4MBNxeQE+-qr3uUOGVXpb_wP=2zdp|3fu$82;2}V*hPUS0lyLW1pgxA{33r%_y+`C z0^bj46L>$M1(N^_#`ENeaS^>N<4!<^aT$Uph{5!}~M4mNlEgN9x!EX5~Gf-xr%s`oe zG6Q7>$_$hlC^JxIpv=Jkm;upxbF^L$6$P{JUq}Rdg3-1%D6ZHO>sX0<74CqZnG_(~ zK7EsxnsLwi%(rUYCuzRyfsyPVcC3HS^{tm-RqP~|;{6ewL(2N+zR_+sT#4VpGdc;9 zF1H)5L@T7~NS3)0k~PjS?n=;`da4RcWCpB#u{oa(&&jqPhEXjo*z)ct2P{WmY-m*MNQgTiWS3VlQ<(mZ8_|{Fq#Y zEXg@jw}&KMmSpquwi{}=5-(eBE}DAxSslq7$&t|#7=eaDye1{1X_K6Cp`Co!_@M$n?l(Vx;v7;hMqbj zliQcb#B^mT)mlm(%Tl(4?zUuV&SWo{P$Y__RBI`DEKAuEy4#cQ&zbnp%oWpGL-rpX zCDvG5k|oRIi)sF+(lE_M`!y3aFf{>HXy3hrtDW3OAAT=!@78ZD65eOZ08sQC>& zkkuQp{d2kx?Ho~9g=s{cATN%uL;%u#MFU>q1R=rD-OXwXiNFF}LO zrug0Ihg?T}`C|Ga>N+Z}N=THWu~ zq-zs(YQ8*(AfgPDw%mb{9GwajQH~Cn_~+4}{U2{gdx^6n?P3QaGm4Q(>D44YdV~10 zWgvMq1|f!Rv# zJe^xZC|?MRKpl~p>+lr{XG9kFwYZM@4fT@a;Hlvap~mU$`q@Tw~2h2c8l zyK-;}1p*&a>55bVC;O_Yp0C}U82Vd#12Mz^$6w#jWOXSTY|>;e1q6a_NzCC7BZgwv zDaTA`(pmBu(*2pFbDq)5+ffj`_$cVOa~K=q79Pkr;XTuIEdu6{#?w~s3eU*_P_&-Ia%~mbb3ixmgC->xqj;WxmIJAFPqcq@ZX(+;K8Z0N)JkS=$JG`8N7WIYJE`MWO`>Yk=>_1V{GP)&(Zr+U%hI9aGWn8(g5 z)Q#io7n=Z*+5|m{*Rt2g7LQhpH3_4egs~(C- zyc}7FQDg#NPOrUi+&t2AYI=gQo!_=HwK1KmJ3&!f#V z9Ubk^WvfH&%hM=MmHqPF{jj&x>G66Su>}im*4^3D?d#}lZr#$;yrrp?HQ-w+!@c^3 zkza|IuhQE*$4y^WoLjkzGyU{$O(?G|1QxWDToVtY}#M zXagxNXScJBg98J>NIXXUuH8ZUmLCpTFCONs>l4^%{&OFDmn#C1UtkzVg4*HHU6_)m! z(yoerw;1of>V2fQ7+bDtM)eG%2Tg;gylbU)n*npUe(FM-(Iy5;fKF?n1x%6 zzhmL0OUkPVW^@F_g@Um7_8~%k{ydA-5}M_N*fAgn^pe4g7o3SkC|Hy9|Oc#g0vtQ1iyts{o^nQ zz0vr;60Q-1XE>@SY&AuysFzT3v;{weB8{CUKjGsLgwiR2#br{NApGSF6s*B_3ch#Y zoA7aiO{VZ_!d{xtUHA^e_Z55-K5jv1ol?sy@-c#Tsi?3cp%S8~=bjR%3zQ?yXad>@ zLy*{uZ^FmT>QyYQLB$0$R?v!#;iH5~h@#%i{yG1DY9IwFL-U;(V#x2bi1Pky+e`DE zd7|QX=BPWt6r#K-yM0@~&t;;rKU9>_SvZ0qiJ{A~{GmdJKU9=G?+T?bL+os$eA^?U za&uNF8NZIuc>HFEZ1~Lyjk@M4F}L;V0YJA^R@%llQA0s=S(m&n2*FITtu3SSV4J1| zlfG*g+cszPG$spzj!V40UwKcQyxVr$Ltp`)+-C`t9cW9I&OOj(kkVF}Qhi!ii$T=d z4zwjnwn_yVvYJ#GGKg|p(t$RUWaU{VmSZYXx_oUt=HOf&F-jvul#8s;;?p(o?L#NX>_ui@@GW#UzUKx_(*Ps}Z?)KXm=%EHbJ7? zlaw$?Y=V$yicL~z_?h$LP3<^W)e1Bl`9ceL--4Do8&+ zl_tTbQeHRZ?WMe3z>CcgP2XHhq@QEPC&+@#%%7T{4VWLXd9!rhJgj$2d7G$MyLJmg z?jFs)=1xHXZ;w)+#D*j)do}x`$Wgk~c}RzhkOq#cXyuBb1rQe@$(eBl0THnT*iL;8hKJ321GiAbZVa*i;7A|WSH8HTI#nDTD&~BRa6!@ zb3{dgKm+2}0CB&vxiGiY_7YqDl^$1X@H^r-pKG&ZuFTI2ev2Q!&D-WvTHDzeX?Qug zn&{doSw+{o%PoFaXE3KSl&^-+(aR%&M`13(%-xfVb-U8(2xX}c0X?OidUvDaoNLs@&Uiq*g zc&oBS%|#VZCpovZXC!E?zH8%YwGsu99(C&&2mt$N1#}FVzr}8-nn$zv!YzpZIg@JN zn5_N@7)G|L-$2!AZml1$s*vS~jLhAv`ao6mkfxa@qDjw_MCq$h9NE&mCz!98t;lU| zwcYhAu)Wq5G9TM42>JGXJ0Y>n>U;=jv3XyxUOgR6)B<#)Zi8|exmG@$6uex`M#hFN zY}o6GQPdQO4saRf+tzeCz$w-mC=Q~sOS50HiXvMv>mzgbsAJJivrnZwdA3Ch86zXr zyknZy^F5eZK5PU*Hmk}|NIb@Xj7{S_O7oKCnNL&cQ+k#6{mLh-9tLE~x6i-;7(urK zCD2(i6RtUa#ri48ScH|5?9q0IyiNy@$@D87%9}oAn_7mRd8V!DUbKuAEG@z8_fe62 z#1K3Ov^*PSxqGNlG0I|z@qpl0#;s(%?32=>1s?6q=6%58h%tCx4C=QS?ZLe#ZJxMO zIfT91A&nIkvxnvxSV0DGth8OcXQeZe#QEP%{4a{iN@p?gqGti;>-gIBDSgWOqVf%K zm|4AdEL)7qo1(H~!1C#N68N&UPpU%Weo`OBu=Uk0nwpQ1!dM;yE&Y%UC0G$+c)qig zG>H;*UNNeIB0vFn2$Dza^g8p<9ss<+4n;W>b5kr^44bO}l;REuH)pY5@j6RH1>i8t z2Ed9;5S1n;Lm*_HhCaoxo|Ic5mdtI`TrrQKl8{;Hq*Rl0HT4%V--*Ib^CD!Xn1t3& z^8&;e*C^(1)=~|xvkHyB(&M$7{mVNb{LI@>kF)Ir5Gi-FX5WH*P@p|T6nGH{x!_S$ z5`w9`-r*Ot07V}jiwDu-$7QjFAH62Wb^h^~(VUvbt)FW5BV)oDes27odOgdQ#` zX|$6jX}hB>dlFmf`y}5Y<$_D!15(O+QWi#f5#s8l*bvdNg%CfNGD71p+OT~l%}m%j z5rKLO28OPFiS%i9q%UDr#vLSbgbVr*M6g93KLEKPLT4svJQ{wAnEE*yqB9%qRhvEG z;w11d^0}1AA&N%F%4CBV%OL9t&wS5ip36Nn0(YU(t-SA54l&xQ=YpQA<$}Lsi5YB7 zN6}TMc@HHJ^R`UtM6`LItr^<_O}x zjotfetZMA7qU*;%y1Em5CFUmwlOlhoj0K`%Q#&b7*{eQJVJKOH{Ib6JF5o`J3y^$; zk`E*4cYPN$`(3I8>GB=TF4&ockokIt3P&W;jM>=K43J^#iwM+LAcc|D#Y z9xlR~pn7YuKT~)vrNh>{!DebTfeV@Io=3n}n7)T%`}BvFIvt+NX%F>>&nZC_;?7uiI7%(;EeUed;SZayXR5$XpYpc)*aXJJc2QpJbR=kAs*#2pw%oQ;yA>gH0_>sc(-(!X~`-(=?0C%IesThwYogtR* z6OEWi|3?<}k3iX{%>M{SQ=+dQd@K5uRzT70=dhNf(vmLWSC(Q+CWT@lSe5NRe8PWq z3Y&0gls^ARVzS4{1^ZveWCusAr+HTYgf+kq0l%Xa#f%JM$hsaA*3NmG$z|(f$WS8& z;0%Ou27~NJB$;hSOvB-93K?w;>unqNcbkF2VrMN)h*Qel<5_nf_2~sF{xGdJC<|m) z62o`0kQ5e?1WmDKAJstgdC+NL{4}3NyA=yjz2_p1gNrDWhbmMA@TFupf$jn=$B%`G z1k@KDERF!AsX=EcLhFcwbPyG|iJ>MPemwmc;iH#hQ%%(jwnc+4z=477L(Mb;Z$|)Ensni!gkLLs@}MXD3f@8TS|r>338s6wWwh8 zvR(+@_9*W`D-@M))mrKv6d!|gr?b?nY{fxMRNfJl?S5E|9NMnPr1hYbpxV%>AEInP zodr&ZO7e@OoLdCXh$QNYiE&88Z4otn?m(P&Oqe)ii znJAI1A~G1)^h`#-)P~NZe4phzbl7|u?U13yHNdXZGnVMs*$5V48&pRl5q4Hb<3S3b zEq*&CuYh=5Eh;kQ^vZ&P=X%iFdK^Ur^*mM{dbt$|u~`dZ4>r$YKxCGs zC={r9rvMCZVMg12%0V1w&F;P#^3)o58ozy-{ad8?u_!2pMFTr9sUH$Yva^zut5`2W zRd!A~mDP=&ljt}EeU0+;b5gRJ0aHZoK3c+0u)6GEs&DxEK0?MDy+g22hMIqX(h%yT zWp9?$urhaM%a8u69QKky7M5P&&KmGG-Hkwnj^jpfzP;J*`NhSp~+j%Asfes9BMa2 zO+mZWyy35K4Ca$k%R#){N+6mwX)+1SlN{7nfrR$b7ywFpmePIFQ27D@$~9_`E~QWF z6u_c=^of6PE{~ZS^s_tUm}33yUpWIi>1=G%?3pWRx@F{o>SXvRy@^9vO>0G$Y5Lq` z_F-pUXJZ>gDK?*FY>K}?gOJ%na3RFSgfsPvG!)J!XDin6tPh;0fBY4La5Aa(Th(nx ziBCR7p3Wy+q9&^f3ZN3|C`9c%iE_dLYY0w@+wr?Y{r)Q&^VEbj(UgEeze1j*L7c z@>B6MopOqiMV*YS5@HTD=ncqUh z7gjjp@6~yZL)_C)p4V_<%zcXK$Jm$yZz$$F08G?6UF|EIA~t1QJ(7`RAaghMrf445 z$G6-f%I9m+_4xf!s_+~r6b#Zr3M?e-hiY~SQ|tkrK7aWaKFn8JpV=e-ZG6%7e=8|6 zIy*#V2nOKvtSS^dEncU^hbhb0um%fRy&qcvwS-;C>r9WZS$Z49&^mqE8=~A{aUEHC zTcHA|SX>{A*Y7J4jpKg6<|WE5O-je_kJ6Ba*_MXLtsS#0jUF7_nQcgJ`(YgWZC4l0zPC6R0T4n$dRWT%;B26ricui_ry4m`2q1haY5?7oT#K z!>80``;?nMgqW}keXg^!kU)fP7yufH!Wo&8Q(Ty#O~6lb2}gr2 zbuDTm=lG*R<_|Q~PK#LHAsY7rdJs2m<5rLkf=*6SsdUn{NP-Hd;c)&es7hV&1HXHq zG6vP}v-RN3PrqOd-$7jHFrfKa}K?H(7GOYH&>mX6Cjwf8|~~!FFG(sI@Cv0 z`y@8-;R7q6)ZKJII;r`q;9uPhKRTo#_)Q7^k=P}r<04In7)5Ps?g3E5*7O-h(cp4O z<_1?v(2S;$Z&*H=tBP=DxA;OcoP?f78^R_ccXNcQX>ARz1rlIP2%g)tB{;7604^fJ zvkVP+697ip8%ZOJfAay1L+Rb!6UoG-9r_>Ak-Pw7Ae3?I5h3=F<}@D&T4p$;i)N%q zvp|sZY_D~xdBkOCa1y3==qe!G&IV5nbvi`SPy~XsQy!y%*4}d^=0op?q!(rPj6fa@ z#q5)vPShMSP}jzBjZSI~Zdu^=EbOk5)4|k!x!}1DPy?)g()*X-UpVy$t1Ky5Kp@Xkv#0+^|Z^Nb{>AcaIaF}lgZL|O*3<*2XH0k52P`}M$- zKI28#H+2idazFN8sP%Po#qfx4MAz;Bw&N{o=pgFz6KbA6Z0e1}W&5rU^;$snvO`6v z;3S~p!IZapL*vpAXJUt_P)u3|JEhWLBetg|@-Z2ef2i)j*#^%iXSrAnz8BypX-C59d?IU zdv?7r9IZv=2sX=!(lF8ZBO<2-4@M*Z@P}})q@Nsd@)2=2cER@CJ>Kvf11vwt&88x3 z`BMmJx$1H4hZP-CL>T3|)S_;xgEBt@4uQ%hip&X^tx~csRDoUHq>d$?>%!w^ zHv`LXffvDvZJvOnpKIc0D=|E7B5ybL=d_FJT~$~iwGJ^ZGS-xW!6!O z%fCllzR3h3bq~c{25B_RxL7|qko-PlCs{gdEjacFx72wWZx+hymURblIbYD;iahCL z90fKYrdqM}kQ8C!%cpGD?Ei^uWwyz~P4)zAr+S)$EISvvm3gM3@**r?+_NB^?K8ex zq`Uz}(plu=8h|_dqBihXU!?i|dl1Cz%|3;HvI=gmq#}QQ&6LZP2k#crJmxLOG;9iqmdk?mo6|+igv&*rID$ zBVcPPH#Z{`mEHN%rQx{Y73GZ?Vq3RKG`5MZU4b6TiY4nzsAcrwuFv(Rt!Wm(_?4NK zA{Stuiv;`_%t5O^^h=8;>^|BviDwzO#ytutQF-z)bSj3Pr$D*bBprAfWqc#c8>i!R09z2xYoxqIjnlzku{>g^$R&-_?@h?V!Vn_U8>d4d zkJY=4@=k4>es@CN?UXmHar&<*FO~PP3VF)CgaI>uV?IL+FKE+59Nejd7$JH-gTBah z4={M_5Qcq;$!6Rsts@S1bp=x(B*vn$Zr@|>N3@=qmCAuL$ZRYfGQ;Hv;_Fi%`S{G= zPDUCkYPxt3y_u(>II^6rB+Y)-GMWm=1KF~VEaC!q&*iT8B3#Y@Zn5HgDX3P9cvPY~z zHkJ&QsB7=ac72)0Tpb`l-E6@`#o zxQVV0SANC_f81n?<(n~xA=IUDv#4Nr+N9OgjLrar7I35c`pZba6wBXx4XX(-3no5| zFgQwG4IMvx$vCwXnku&;AHY^dcpGupIPO4OhT~# zpma5q=pE=@v$tM{Re>Gv_({1s?pH#C!+v&@*x9&GlxKVlr#JNnus*tk9WGOS7QKN& zA9Fy&R-n~Vz~;6gcIpUUoTaug;}a|^d(|htM3a#D-B*a9<}M0wh%tv}Wkuj_GLh7O zz#${>Kzg&QKCaV$qrQxuX*hQSfO;KZ`ju`Z>nV8^b;0x^+ieekY_#J~KI#wGz>aXt zV!Mq*44vh_7)@nRP2Q-R&u*PX*GADcbC+n`Me;V2>L|b*tIX9N9E0_~PYhq~5MA#C zE~K&=8kMVE$`{)-?2KdkNPXBsC%lmP;LFs<4)tZ0MCojc`ZOtpK6gp*IsCP=IOZjU< zFcP01qN~!jzUY^*isV})V=gY~%f%U@u`9Q=F`rzJgXtU6V3DcJpPPl#!*}i5{NWxCyyO6xv=Y8FF#hFJu)$!#-J=o9=h*38X3>i*chLl(TuXHhAe}7rM3v zKBXR%HX4Zj!4%@=v<W zu`5l|aLi>!O!?Rdb9F%Nm#i~WwIuLJxD4v&8P3RfbbAz=F3|k}K@45>bqoo&*jR`L zcIY^O-imNkPW6O~jOyc`;5?6Grv-OXL0BqQ%SSBINcl*blqnxEN$Gy94s3&xvo->s zrPoMv@q-GmX+KJF0o8-Uy~p z3zPP@uR#NB-dz?!+lVWq9L4&#`vKxj_0Z>FRv65H9yxQpb4b%(x1h4?kur36ol9fYI zk`@wLr&0^W`ZN_Nz3M2|PdDiq7f>(LwRb3hdUL0<1*Gw?`x)kv#4b@i;kiEmj7NJ5 zwUQ6ODZ~&QV%zYQJ#s#vdRTWmrK#%cqza%)HWW{O334*Zf1#HTQyG$n0g34x9*^^kl$0oWdxR=&2SEdX~#l-;b(YT z4C>PNHH|rk@{9Di%z<}k1NJ1wIXPFgH{|1h1m|?-2>LBx1kIk7%*gAWRf11zWp3p# zA#p#^2o>8}^Sj zs4+y_-y0m!cOfmJi29Y?eg%h;Ls~G)v&!g$U8*I?r)>mwXZU2*5d1O%Q+L1objp{8 z_~af#@Nd+$v9Ki-9ow2Kv1Kq&Y2FrZriK$#apZvxgP@*6*wDawmZ3^?Lt|mw{~f!X zc(aVW$BJo;C!B8x=R9_gCLlHuRIPWzF4Zh^hVz&?$lk^yINc&J$X#x3H(J-*!C zzKL&2s;CtAq1{|q6E70mzRW;8AMvyF_$i2w;@PQ92ZHNih%&&@1;0PC-(&3eDEmFa zeh;(XL+rOt=Z_OG$DF-`)4UwkkvPpab3X927<^h=j1j&hMi>e{7(##;AH0Z(-U2#7 z>f|+Vu6M|Xl5Vlehm66Iin$c$jL6xFxddUzdMTwQs$1X1I$=&8ao*&cq}u&4+ZDm< zOtk5<(2xGii+`SN?H=EHPGf_?XM1`#vfY7`F*))l$>CuSQVki?EAbYstd$5O;+LDPCK~Ga0V9!@1JU=lO&rjq~{m@*T6yTJP zM->o4T+Quf?*Dj@A~d%b-@f49$bE3h_d?vjA0A({Aa8lr1d+XzVvP{0l<1|OzThtY z6vKSRfN>pJcP?nmW>WY)k})?zeqTV!yQ@uFhLbzi_*M<<_u=&G#5aeIf3!A25BW_Qn(VErYQa$S=a#IufLYR_eu7WcwX zpk$ChM3p2w2~ZCltq=ylF_zcrU{Vd|(?%L~uiQYiFtELz{2}PvOOy z4cJ-|kmTt&k~|$plG2Gt-nE*@*$+vtA@w*US>8Y-y@nRTQa=vxGolFRZVbyq^q=8Z zGI5fCgu@bosr`32^c10Rybp;+~u13EbBehF=4 z3Q+bcEnOf*v-N&Z1fH$(x>h9d*oOK?R{j7bBa^weMbbBPs0=HVCo1;gm=E=GbPF)N z!Y5xN!TgwJJJc86WIaO;vEyp=ygI;kaV7lVdtRgKCNL87pjWSgW=kf(@XZ;X@a!Qt zQnhh|S1ysNdrRc%mjr1Dkl(3CPo1y@pnF6-*e2FyFu} z?|{)Dr8lHxtZEuji~b@R$VrlhHKaHw2TfZViBgf|4i@6Zs|_TABSMlWM-0K&BNyPB z37|lThoM6_EPxlD>4>CzC^ZzY!ZW)Ez|l4WlIzU?t{(2>GnBhcy}c8PFYu!| zg!MTKrv?X34KPm99>Cq6)a_8bpu|Uc{*m8+({Xy!c^-n`fpx_0)!fZ!IP4dzMde}2 zBOq`@8dvjcH1X2K+1Os$s0Bx2u}!{<*hY6$GOMLqs1tJ`YKoydSYyR}9!p_9xfBF2 z-pAAXQ8~I|Zet>zSvzoKBg<-32E5nd$$}K!V{5(*$f#x-M`%_Cj-#y%If&>Mj^=EL zFYAqA^zGU$jZ_-g>Nb-HWzeD;NEqNTFva{ACQD~oq?1HtRz{Q{_fWMIbqg6&LbCvA zR>lDaAt`8=nV?AOn3ZLSSiZB>Bz3Z;$SLB^BCpiKN6nDB8BpiW5HpaW+_&4A!;z>>% z=sL|MdYR%jMPBAWupxl7@)`z&q2z|&8>TGlGJc+;(;P;<8>TI`vT2#XJ<wzahuP$ANpvHe8?Q=Y1C90 zD{W2WwcM!nuy`M;+g^e<)6#ZHIqcFZH1d7Y=`EpVPHotal+kg{!S^K5HHgX_==`{bQ~dEPi6)R1cO8Q=0v z-WL1;h$ZD^1>Y3I7oNPH)QJX*#b?~a%9Kk?jXi(D5|*;@P^L6i?y*W4xG;pNwLLOs zoyi1Z4_`Nog7kGJ3j*`HOr$~=rh7w`mWVO55Zm1?84$_qX;+3U?&(IDKdxg9or=kQ zi7YbjAP-ABKC(OLW-+{U87Mn0_ihv#zw&GVV4*1N{R+mDE>B*TbavjA2I&mj+DzM8 zkHNKT#b`*bspD`g@fhFoSPYa~WZdT3wH(B6OUfG^-08!ipvd?^(d4&+FN1K6U(?tK zQ^_fRZIZI&udPx#IgX8anUC#dKDL+n*j{F1TbK^BWri=j@+%V?l%QlCK~H$b968e9Egf9;O9w^C(nXZI}rJc!IY?_~bI8nhtAx)BK) zr&-;$33LpNdzO_Nb#LHYTtGx7!~ZgPDkxCVLX|&|AoaGY52C($Ed)6~Q$@_Vn4GUY zbkoWlp`(^)zp_|&qsP4f?5T3Wq(6g5aFfSGXzDlk?KInv1#G$L9?xGvE-_!{96T3F zUWw4`rqWJ0vs*j}KZ?#er@DVL@ICH$mkuDRVGprk zUfv8}cCVwKq42cfAs`)0B^~rREQ82(*qVaLY9+-Ni1Oj?6|;awF3`|1+y@Nt>@yw` z_LJ+tALkMyv*(0s^3BQvK&zO@PG=Jw6()=Fk?!SmvQVE!j`~qo{Jv+vS)*NTLm`%k zW`AW4_^wM`f;65l#j_^Sg8$?N#jJqbBwmi{qWbgCZhC-nH`}*7Sfp5+O??Cux)T() zeV(S3#&N;%Fm>TF4OW;k0`tO zLwe+9v$-b#KGBcp{epz^dgK1Rkd#Hatwp5uVPEi*R;O+n2_iObqB1(x;G>_HVY|iY zdcHHui+UNp&Nhen-q8_@UT1Z@aucRqx97v|KvR0E8h{>kJm;Y+LA?WWAws%GhVh5a z=iv^ToS*lBzPh!6JxtKE0We_8Xx#r8l(7Tm>8rs1c)W_PU)1ZiVnScV%A+%3>Usuv z1Cj^K!%;0sx`r%>yHHcJ&%Ok3p-kk^{so|K<$FcBw9q{Y|8tkxL5q2O4ds{c_+u3J^Y}9qck?)HOzJcqZ>4xP zkJHAZj^%OU12u!k_fp)%w@~~Q9w*y` z`V5a}QT$Il?x6SsJkHELck(zL`_%>>&!f1+<0KB$Djp}Jjkoi<=M0HKVmzZ@gmGBDEL3da6+e8Hafkys zxA2^;JSQ7D63X!N0GLn|m(~k4UL({8Y15HXiP? zt$+${z@h`GHU?k!ZHStO{l-0_+>4%JdCcADYi^f1BR26QY=V2WcHF6w)e#2a(_jRi zs2hY&B7?9Vw;`U!jl(7whZVYo)f@9c^uwRoODE6}M!;Tem~Ki9p22OL$P4~Mf0apa zJefajygZ$k2fx9~a@tR7C9GD%XqqIQhw+FmK)6c8g|O)Irdoo2L^03a)Qn&OqL@i< zYF2Ox2Iru6)@-Nul<1vEzmK**iH#k_|3GnaM5biytE9tb+9ldH!??+N-{z%<*)B`G zqJ=_ECW5OWH-n-Wx*6M)`Kc8Um$`3X_o0)4AjC(QpaY9ek>>EK9fU*0PB0O)0BgMPydE)1h z4UI57r`MbR3s_)Bp+}{?2g?jJtf)m_7$?2As1WJW5&h{z+W*KDBC{4WK|j3A)gd`C zMMODe7pEK}o9aa^eIW1pp@b=gK!Vlt5F*fxpyOzEJ7Lp{(UC^HQ(d(l$iO3}$Rg%$ zSF_d9oq0|qv204;$DyNQ>Pr$G-z8T0$GFcj)??q3zXuIW0#U^n*NEe zXIi8|Jm3qV6c;+Qw#RevgoO(UbpD3^nbn(;{NheVdl`=nHHnmVQjKZC`c1vmPV%=U{jI~>WwOfj{`z?8Rv$dP$RqP93 z;-RO?;nP~AyodLDWq3oxIp2mZ!;HS?4OeSkyt!r$PHA7k$Wo|mXLeKA`&Py{HRnQb zDm?QFmAAd2GgAREa*}4h)JwBrKZ04|tNI;p$o>^le&uT1zZTVEE#GpEN7;-wIC&;- zcjx6vsXpTyuARYeU~=~;ZIjzPli%>T+HOwu;`vB#sHipqhtjT4AzHp;Yoa&80X19G zJVXjzZ`+z1C`b7-Ed}ME*Y!m(8ShNMA}}5N1F=RC`cbx>v?qo+WQ51~wq`FWB>B+i zb!oPy8Gs?atjh(P=QWZPo>xgE+;SB^e)$d_#IrU@0YBu$1sOiq_7zj2vH~j|2RsOg zkMaS93kf$)Ubd#sA$DRy;!kW{^pS20PX;(M!_AH=wW1Oc#*Y`QF@XSdy)kSx`!k?u z?q*k;t!XxDDwhe6)sPkt*jR9d%1(Ba`%hG&=jY0MJ+59`(zJqwLXF_&mVt*~c37-clMpfgWHafKR{wTtsO=>qB*X%U|NhU5o>f*Y%n0FW`A=glUU)|ke_Eme!lwxgcOse zl-i7x($TXWR1=khe&q|V>mYg3gNXMynqhEb_Ed0_L|MCK$#C80{M zY+8-Re&yzRnnp6n%s@JKAEaz8MC?x5oVbYn1kLDt3n9OmrX2*pWB33VtD@Pr16zN2 z7nt8f+i9|Lq=(c|#5rr;vIxfr+_Gc)f^doLUemR2$oqihX$C3479N?Ah3A)`1DUu|U_!@(!@dzDaRxk^MTem>K0C8gve10Jl$+qln z`_baIt=*w+Ko*lS5JM-sTV8MyW4l{kafT3fG&yn52Cm_Y4UyrLOQp!ALX2PwZKrOS z5AgI(6Dw0ZBWTQu2bW+}M0;`=*Hdiesq}m^xM5@--tk0xF z54LcNYm2REI2MZ-zAQ_#FNPXQ!i6SQzBvnaS194E3@b~s7wW|rJu43WsuPd4BH@vb zYEr33If@PEuE(iK`OcVzdn-HwY{U2lloU#Q@XeC_&%wliTr>n@Twpla+JRXt8bFH?f%@|XW>!5@Ukd`joO^Tws=kw3ego} z`MdlbVME%8Ip8GSDa||~08SO~8s2}$`{s8|`A?B^??Jlh#Jpk8DaycGN+BQ{^NBLp zu|}Z=%#|p~Ap!TNCy)$Rh*6<-&BCkLTUcZF4T;ai>CboKJuh7K7P|_SPl^;(ed06n z8Td*v6@`NEEIklBUA+|yK8VThzL%L86NR20Od!1_iO@}2xfQ?8Ti@`knnLe(!wVLD z;e`f|ye=KJ47ZG7et!@}+nI;EItDi#tX^c8PiY`y36(*5L8G#O87%HqlW~V1c};nN zY5MMlV`m1<@{Xhko((-VIXHxuqkCJ+JhVpVcq0)#txjmz?!EvqdSz2KYUfB6&nskU zjN~=A>LqJ~tAuhalyj=*6)bdIZJ}94FpFvjhfys&1X&UU7T3d@q&=xfSxq?R?tu*O z9Q+=NDWMCeZqvn{1Fa@0#cg|SyWEo#8RI$FYD7)xjBw$@lsRMc3M1Y*Dz|OMom$;U zd56V=N2(?SO|C7=$I3fQ4cxAD3KNh^_25jqQ;S&Lt2&%X2lk$% z9sJmMj7_yKbTw5-l9CR73`s2No041Kl<=~_lVdF5&O-$*$K5eGPO=)?Bs~CreKxi( z++5rQzueEFkEAmBn%i2abiv6G>&`(BX_=KKx=n_Y)!}Lo9q!NSTpZe%@YE(Pgc7Mu zDrLW?L#K|O(`Y~R!+tIA$HCI!xGS6gz$00zGy{ZYyO> zp)Ds{?puH-9U;E6HG4VKBDv2LOnB`Oq&e0U-skuihLDJDIQHTFH|~FcB(h@uL#2*F zlao#%w9x{UJDqEgz1v=hGzfbT>b7NVxkKIYQS2f&kr6&pN*Rc zd}6op{u}pKfvM2-gm~8_$RR8D2r9v_@H~`+F3_nvDQN9%a+0YL|Ak1JoNB88T?+5wd9T8(S1}Eh&d{C|ErXOtmCiq*u|8ctF>%KjD#TUts zoQHZJC)9hA>Q%FP>rl@GkQh#8#MWtk3~BnTOTka#G`;jE#v}>T6z30le+eF^nkIq& zn5kz07{g0Y`n{EtU53!jNH%py3Y(WPD)$%NU~;%0#2ww&Fd5*zRMVJROK z2Woji?~?v(%9bYaB6Ugd8+hozp$EG%y-b%B&{k0B9+9B8=c50RxrwY3a=}XKk>MSi z(0L@s>) zkgN<@@FY#P49x%}fT7C1_#z^Q)!az9T?3{-q7P$Gjktn`XicRTUJ5;*;|C=lQOOc) zV0a52il9siJzMZ27wp5d3et`0{vX+;C7lnSMNXw>T@o7F|J=aZ4?%D0lG9i|-scv! zhk5=`%AbpT^f*4+<_2CijLObI86aUrFH}Rk3t9zpdEUhlk!CwK2dHO4+JR7?13J%J z)eC8mGf9~XnT-Jia>0=sXabTs99=dMc}Y6BiHePz>XD31I=|OG1_~O2HFCk<5D}#5 zY7nxVXaZqqeVjnrXHz$w<_9Q&PjpZZ-iqw7b$cNOReCBzp`NP1+Ys*yW-T*$%Y}N& zPV=4A2|nOH_WWp!`4Is=d2+!rs$pw}DOpgr;II`k`;ntQjhPCW3lWtI&ZjEUNajx% zGM_`m8LW5;Mc-i2gSAw%7r#Q#6D43I4V>eUTMZ=GNv@l2o}^Y_ydiTZtKZ7%C*jRA z5cbz^UaZ-7=3t^Wcbeb4jSB*~;6YX=6)?#YLx|9-aw0-9$cb^qoU`dRHw)*jjOfOf zhZ=0DQrCiHiKInRBFPc68UPzGIi1*iTMM>J+gh*F(qcXnea7Z3N;78nk9DGNu2sOs zP1qnT)ObQMIqVYw>?bSU&8Y6*q`~WJ2&u=qH+e!C6cQ7BhJ2 z@30a;f4uBCg^^s}$K_2`0||U$`eLE|n!qxueSvQK)A4QO3`WQG@v`IS_y?2?oI0Wd z2+C>Tb^1?01f7_ul`SIP04R*ZJnXS3l8oX8Zy6)Ths%fAT9m`qeD?P zwWT5lMQDnP`KY?ruu&zmQQdeZ8`XTEJ%7-NWq(g25#cR3%yWc8fQ>%f)Cb|ChYWE- zw4M~u{wNPYoqrMK4>-#6sat!;89xK%=u&54%K&<(#n7kKHz@j$AoVQ+u{Zzg*ze`o z-;YPmG`rOgr~wdMF&KjX zcGk#eC_Z`m2~j+5{&n=04~pKudFp?^ga~LoF?MvmOJGpaWUr(8Od!yPoq(l?B;07d z&QdHZ?;xwFzjn)At7z$aH@sEKmVP=z=ayeEV)0!@g5BTmtb&a3h71q}I1vw!@(DWc zarkbi`YC+*DReMwNui7D;vVKNMc9^Z*u}A3NWks8vJ;mnhNu?XqV#S0r1HQC&HU7BrM(T(;xZ8ja+FIV;c)Lkx@1fY%V#wrNM~4$pNq349yGUnpgrHj@)z;(SMLat@WQpq9S^ZQ#KXe)9f{9m5L6Yg3 zO`a}UPN5K5<7f)uoxl()Wr#hsJc`&<>bInmP{XMotDh-j^tUqb7Ha4f^rj_R^KNy{ zeJ4`+=Sm5QI?$j}^X%!UV=D zAp~(TQVf~3(m6M`b$v22zI$R2QEWjW2{-s8fUHqb+~jOP{)RjGOy5#YeAYXW&2$N; zQ4UV_tSL_RWCUqJLjC++%o5J}^YudHlhUbfM?P=XPh^8yrF4S5g__BmYU8dSE`8_o@AiB_x&+mxX{L<3Mkx=;mdZL^7 z2!B&XBTVKa{HcjPde4a``ftepiHZIVHS0Ig`l?XOm%zjnU$TmM`hfJQKban|zN3L02@8eo2uS~w_~R^2f|Yn8YADm?9|5+%@8G)uMh%Umh9n3iM+Jpdf^;>7 zwSt8ADy?+Z3sMnS-rLrb)%Xcr3otR#V&Qoi@w}>No+X}F%k$zH^(_`=pJ3>Nwfo8b z6Vqd*(;`Sr=w%2J99{6nCp=U{A*8W`u(5Q|^S^h>VK)0>m);#~FtJ&kKWy11~0U zW|1aL))6ifSq1z1Y61&=UCPnS?-q}dFU6!b$1lA!zU z3FOYuYq=?epqxe^qD>iSW=qQBwj?~aWnQ%qPfMX&+Z}T`0;SZH)hgw+N-Zp0wFjfwtIWn z?iopn-?T{$$fmnJpiZ}G0=Bf`#!tyIXj{wWXj^xdZ7rAfZJ%VMwNZjZeA_3Mv^LkS zppz;-fDF(pCpZKHDv3Dpo5RPS)6)ya=!wwJYxHw3e)taFPb@H2IPTE)1Lzs!g;zPL zqqA9zK8fT^??gCFPm4M)L?_s-=d)#l+0Ua!tTO59wFUIrxhT8+GNB7Li!=BrW`HM_ z0~d^OhV72CcrAtit5wWv6=PWjq*d@qz3e_ z^Mer}5EE>lua_=&{mIH_iBq2{RtuF5y?# zf4|R;Dk2ybm@p5#nxlU4CEGntBtI%o03ZoC5x2(yJUS=<#%~FlA^NBB_HTaepv^h{ zB)W8c1rK}z>%>9O08Skg0LT9X0OErn0H5~^LV=j*9MFG!5Y+t9!J2b@G-3RC2~vZE zH`8!q3hrxs95HLSuFnqAo(%z9TpVkE%fHl~jiF!r^N(wvKsk{}UosGX@Ielks8~%x zTViRFNo1gp3Li19d|*HNDR|K-;qaaVO#v^3PJ>Z^Y@6!`@TcHK=ZM2w#Nkk z^)sX}^@Bw!Q&hpBVX`fYBH5TIc35MwE=B>l;B#10u<^q`JPQ>_lOe{=Ax#~oWp?-d z*(j8dxYyH9B8^)vy1hD8eeD}uqo5c({VwVp9RQ?`0XzV1&@&xeKhaUi<*4B0@fmScpt>-pf%7>k&}pum zClc`=l(OGnOK5|#({!{MWf_K`>?l1mk+O-X&f%zn#{b3OFjS*7e&5be9YEs&`lc?0 zO2CvNFi9|`BgY-hVd%>R7qL!U_&ZquO>BTac1F7yxHFGv2e*krD#2Y+3&G-9smRjF ze4(gt<%F{~%Hiyby_~3Dg;c3}>}y7RoCe;9F-B+LDDc)1Y(%)Qir<m_oNm|@i3 z#D@TCe*>G%07?CB<{;E2`AFw43_j85ay)Y+koz76ALQN*sDySua=)NwCX#yqs-t7n zzA%nzl-d$Ub%2zKQd`G2E);cn^YaM)?joJPlcPu;w;R5l(VyUdKzcC#j#2zp2Dcx7 zSD@X$i@zNVJP2M&$PFa;EIl)k;K%Vd4g#FN-ztkSN0j18995m-aniE=hMrh;$JhZf z!-4kj?a>T2#+ZDMgPgW;)N~PNYq}lP=v78edT<_o!c3Z9fLibcaN<3ih>8de=;FWTFPB4k@{l z$C&VjM9D@{$EvEI@(G;!;lsR!vN29Nsyg&Ahr&2M(HUsB_Q$6%MtJmi7Yf0~C*$vm z=%_Tp=h^`UKTb<#Q;Ja)jT+HNM>DR5_QQ`I7W&~A$4ewSxi$Ob{&>MKgrU&fMevRj zMyErtw-TN7WNN(IgmXr8;s)?1*t4D{tx6|ODTPraqMPuY&IaUSA4W$sWw0qT8(lTE zEJhJiQ^aV*9gW1aL`L!$Z;;Zlni>(({J2P7WcpJaG>R(x9cn(PQayPNlAvWN7_q+J zln)#aJXr}e5UVFN5Z1D=$=N_5K2%m3jg&+qgAD_?K0}RwYaSZr5akhO8+piP!n2;1 zvmaF-qpDC|cnG&yq&0hO8V68MbgLJFSii@R1=q|5ls9sZqqC#TRLdrJIAKmPB0xR# zQ8WMnYRQ)txiK2>^KU<{8l3B?f85qsC@kTo@qOsSv+e@H1`lxZGkhzRtm@aVE!;8COS@Yn3 zNDR<3^91$R!p9BkZ9+o*d*Q*BkbEK9ocbKt-3r!RiZ7Mx)oJfAh!-b-@brhc2oMJX zdI)ZCz}uG4>i1}+{{8La>pr4m6p;o(QSmM%j3$l_H0FXuKClM!3cQkH_9H1Ee5YBY z1U?Bp{+5p>k$7v#oe#w0G6(!1(3C=ova5c`9y6dFCwrnY0Pjx0%Tt=D8QSg7@P|e? z>CehqisJys^a+CY6r{|NO14;@#7zj*1^Sb>gu z3<7@x<2AAJSOL5&54nh*5u&HODY0Ai;oG7e#YmCR5P!Rfr}^xJ3_N)5E9q@Cm)$8a=&M$B+JS5Pja)!~Idb zbuJjIhtu`&5iMm>B-4^=%ppodADc>lxnFk27v^ib5p%k{8S z4{P;sr5@g;hY#xEQ+n8;huwPEr-#Gd;QeOn;Y>X&*2C-c@K<`cS`VMl!;O0Qz8-$5 zhr>EJ+>`Y%TMwt{;e~oQUk^+5FrbG`diXm%{4YIxMGrZ2LHN5qpV9PS;S1*p4F(jp z%;Di+^#;o??bh3U!oyiLfx`MFQgNWByrQm75S9sbLb*^Q1aP{q5T*!=g{Al>2!UX= zv}9R@qaqNf2{;77iv6BG^Zj$?&EvT&Yo70tixQH8cTSPVcS&LnZ+GdrIl0rUsh(;_ zS#9moCFNz(lA3BqRau>5S=r(WM;Y=ZsbX2JME8kT6&{naWJr? z`dUXdKrJUUP-{u`5@|`<(j~uQ;8W*Q{Uz0lX}}d|=~xuJ7HP+gHNik4u2UR7$$_fN zYU(7%(k0hd06GmPP*E3LDmiK@9pz<9mr`e-6ybDcdCjugB}*$7JF?FzUmEy@qcT`s z&S=W;EQ=#mT_**C?~8uwHhcXf^AsHm<9UR&j;t1TW0#dMS zX?&7sHdzOR7uLlf^uMO2x&o{9EHDoOheSh+;dORCwTq9trnaJ*)Y5eRcsM>v%0iOor=+H01E6Zt9n=^fGc-~h9b=zyNSk6QLAZZFI*ha>q5Q4^ z>AMG{R}Vy@&e@ZJPuAM!fsf0ZN1X^UuQQ3{rTT zA^tDP@bmsf+aEvre>LZytpMt21pY;Pq*Oefq5s{Xe>UD|`M~-=Z?y4R8A3eHWArNQ z_@|-qHo2+!_B&catCTy#cip}Eo?qX4-*4{!j|YDHyWcM+ z{=}32_1CAKe&*Tdo`2!RwJ)t(zv1OqUVZKL*0zo9o8IW??Ap9#>$dGXcJA7}=gqg? ze&^l2@4dh8gAYIYxcie&Kl|I~fB!=5`7*NqtABjm`^~rCegDIOgMEh%A31vLN4$0W zzqug{F7SWWhVVZ<{{QLz|J(HcXB+b1m)(A zIJlGnzZho(YVWBHEFqggQCXn8N(Xph#iBqE2X;LvTwGSolIWNE5&)lI3xG-R@U2Gs z8wnP{5zwC62=mIMU|=x{@VPLsM32D^Q56i-#ZrQBMaAOkiiC{$I7U!$QB5_gH7}@# zWfH-m_S8l|J*p$1oS}*kN#vpsbx;);pai%8C13^wfhW)f)<7O(z)&zE8W=uT2up-& z;ZpW{t&k&JBb<%zRD5$7{7JC4ED-3IfBsqh|8DsL^fm?GfpDe>%Y}Mad!nDg>J7yI zpTQYeUN4+0OalgW!i{XqzPc-FR-8L6W`DXKR;K_cRspM1F6b2fKtI0(8vgQ%c{k!X zxQsM=Ry0`sXuH8eL#jzgon{eIFC9{wVz&r(DOIp9P7&kkL4SI`H241~{HX&fhxPq!h(D5Mx(5t6_* z2E1Cu6z{7zlZ|DFkUDh;gP8;vVl*5);* zAneCC+Qu+R5c2SiwlR!O6-G-b!sx{oVf6fDVKl}!daAuO#bFg3n??%`DNArH9wj*7 z1m`de6Gr!r>bCC^gy=Y5I1Pt5d}-rea5};f7GcEVRAI#Y6k!C$IpWfcTEn<>VVsmE zj6?o7edp93v_UVF9jB*MGmj42IXW~n= zV@1!0_J8Zrd(vYg&xAj^a}5Zn*5ANHM|5i_(7+cmV4-HV2p5WAk<6C7}JB1ek0c>%0^I zFC`}l$%fzawFUa{^oxRFXp%5=YHE%lHHmP{8GW|(oQYC~FdpmqB+zJ7?y$hn-t_L& zU6$4%#e7_Z59d`Ic=i9ZcQ#;gRc9W52hb4X$HYWK)R+m?np&eoqmoD>6Ci@-V+2AQ`NhG1VGBw#AQC+_e?P5ZLOBsT&nFD!M)^u5Oo2UCWbgEBe%K+PaU_ z#w~r;kNv&(o;wVaq>o+gs?X-e|NP%`&U@Z-&U?z~G49VydF4uABJ(cF=PhjIq8Oud>^y{Xi5%Mm;2m(@>X=0xpS=RUj9W=`W8KtFZ- zbE!A;q$y=HOQv%rI&5^x$mF3(0|$k2YO@O*+qhipb89N+mYZ|y2+pm;W!9bM+&bJP zhcCrWo=YZgvh5bA-Q)H8R%x{p%OX8f{WQ-?*DzVux;T>Soz4+F*|4)d{_!f2x4|fL zsmx=JXrK17qvu1Ma%I}L%U4tcX)c1Ob@#YQvO#zslM`BSlf9^?PST(u4#M+xMVuz#n0k2a|}Pvb+AjM zW5CG~d5^rVIP2({@w~nlkh{jy=~7I~I1a>nZ9g1{_u78=qQ-kmq$Jo936$40`-1`b zmCL-RwqDPRd_Sw4*o-$wv_-y>MVYx@)?ATpt8`g75D31r4_ZC84%T z+6a<1w^ms}8@;=z448y>-8v1BwXdj)TrEFL({*mi=cKhaL0SGg8!JX_V#$d)mB9c{ zbMLFY6)pa@U|<=+$(6()szqW_LhPv3%Bq(2YJW{293cQ)7Oj>OUCVf*zpRlL-dYF! zW2_v@Ke9tDmWFu{sA>;UctP3fm1WC$Gw%=b$m!1B5aHpoxpiH&m^b!T{_kC@2!>Ub ztf*_|rG6NjmA1bt17Y=+al2e+dS)JVb5I!k7&iNWx)upUsD(4 zX*Fc&v@|ubbe1B8$CXKi}@e!3PRZskhf z&TvOgb-2-9XmXC~R<`<`x!yBw&sm#ZoyRhE6!-}Zv5Ig`zrGnsOP{O0*9B|&eu<{6 z6K_<{1&u73Gj_3-*e9&Kqh)rpB`t(7d6Lw&wN+ijve51s%cU)(?(oWUW;K=2d$tM$ zD+y*XVRC^>8!H=+I##yoj)RC-2Gru-1+siUHLB(Moa#n@fYltXYFVKX-KFiV0eNBH zcJTE*I*ayXmqle|wzYbFfv~lAf?&QiG(5IWM^n{Uf3+FwLu%1nf6Q`Z5wEhwY(2|Y zv9H7%vAlsKzs_17s9PV%9J=gcW|)z^@_(DPocO2-eKLcOWmPzPE;5aHoBfrc#%8-? zms$PtS#J_5RrZ!}Uph_uwW@4|%Kyg7XPz7VCAt8(aL5*GMXnCm6T8)3!;RN)-QBGg zmRs8+>?xGR_N?ms=q%H->DehiSG73Km*R3S7mUE>F*>g+1pQooOcaDV%XPvL| zj+eQgf@{H9V2r&*(LwH^$RCK24}63Si_^k}qrBd#wO?^jL!^K*4{)dHSOsYxp=(4& zu0s#VwcJ~Mi~BM1GLMnX2W_I4PZ&@FrGY0e1O z5g!{>DD$29NsrN+sSkXL?_d)Q-Nd-Q zjeNtn6*uKWlyxX5_W?I}l{wf6c7eCRdtlN(am@u^1q;AZPzkER<)9vX6SRYk;3jYz zxC{I(=mviWegvKX&w-b~>)=1YAHd{SMDoDbz&T(QSPM3QTfq0hBj7pkui!24J~-%A z-f4i7!MUIkG=giv9pGN@0GJ_PmpL+t_lRq7f=jZ6=N~yqW(n`1WQrV0v}mpzFGtJC z;*mT#g&*KPU5a@3w}kh4i^V6G@K*FPxlk^ZGC5Pum9xdm>MiD*`Et34_oG$v4LM4_ zCbNZ*{A$jkg6LTbtgrc!P+Oy4tWRIm=Bg-H%<+vrtAY{Hy9i%>qkTKHw7n$AHm%G| zE<~KR?0?ej18otLFgGJsO7Aqn)>T>+t&~$-9&8mr7x<(DcAS{74pwLjFPWqew>u$9|t)!@_0g*BHwHx(^D_OMx3>xoG&%i|fP8(PBt z%=83}>WK=PH08L>zOhL)G9f2ZYrLtHnw6EQmufJjX4>TIk*pPU(WPyXie`TxD%RI_ z+CVeXSWe5a+t19HsAILArea#Qa#G!~hP!u`V=1MV*5Jgvy)?(0O(~{Y*0oR_=9Brg znE5?${DnMldi;%f_kCUDpD*|9T=&|?AM5w!(ICqp+i(t?2Mz*Dl0L?!WXxeMiB__>nh*f8`$>;TwrLVUE zYX4%OZ3ltcX#yUgUvY#Lh^5&5*Kw$R3}~NkFuV!YvG8?fmEQ=f9rj~!?G^cfNq58A zzb!!9>jkR!1kf@47-;!VftKgt6!nkeGabJkowMwH$EvGGXP=!`-|5j{(%L6I3Qb!3 ztVdU`t?$@tFlp_B9)%{YKGwr+($nmujBK^*>m2LRXVNq6q{K}67?UnH>0?dWZPMyn zJ$Col_KvrcGHBAXO}f^kJtjTZr01A)!4|uIzDajHXs4Y^LDZzV^|6iylXh;qYE1eA zQ|>eAk4?JRN%OZsCd(rITOmDSj$_jcKZUI4k)97-U|*(PGU#{Gs`p6f3E(Y zTmLU@KeIoX>CE>3zou_rZJ!sP6~C6S?K%F`>uvh+e>D%D*C+NPy$>pX-sS3tKjn+q zFZSL4p@;1J+HE$E{K)A2+~xu^ZpXHh-u6?Ym+6SlH0|E+VK?L1@9~*-<8w2%|IKE0 zm-fHe>2vGyXWsCBmw>so*zXeXeCA#GA{hLVFA3+m;mXRfZY8&HBT~DmebXG{+pTZd zLU)hNH#{(6-7*zlAG5d*{pTOt^`OV-XVMKH**V3AANz#*UZejw`u`IDW&9XC{8427^>$6nTZePq-I?+IR95n3M_nY)(hN}#h8!k3nVAx|g&+v4^xrRp{HRCosnFmJaJItB@ z^ZjqpLYFE%NxxRGj{o*1nd4@`=V`6=o9G}4}_XG%Fnq$;;XDu`d=Tu z(oa|4{f6xapJ9C#N$q3}Jkcqfm}cKBEp zxY|4p_IgAfMlOYK2HI{1`~py&SK;5yA&!E)2X5!Z!`;}tAATOF{)_PXuZa8%ISPLO zv|VM-3AP>Oi%!H>6BCvBc`68+Nt!*>|@Zuo|i86WvK!tVlY zYZRV+irqI4{O&y7)o4EaD=u&^BJYO(rhxMw`F>@fb(MAhndK`u!Pn;)`P<=53+(>f z2zLV=?-scFOyYC>%o+R};6Z)|ZaK^J9}b<(dLdt#zr(leEB_bJv5&zY7GeV(SxAfo zsQo;6CD8s1!BZD8C+JLv&j#C&3*joD`Z4%-MXWpW4_(Zhg4`$Z9b9-W`~8rWp9jUr zFT(c~+j5Opy~dyy!f8yhZTr3f36; z9{6XV6IuDD^Xxg7vURp9)|Y-J;#-AS!3tV ztr5BN651vIZg|$E%qQ}0_{2JVk31KC7W5$xz%Q@me=>+X1RqszkM{(40~jJd3V#@& z@5r)_HP*lwo@PD6+ky6f2rg?xCf^6|0ENgy@S>~e4{|ZQ9@HSm;KxBN@&LRCG$6~> zB5#5Yv%y2G$6& z#%3o)X;XFJ$H81=jq9G*&io>4ocG6|5Lx5CmtTW#kTw4NYfz4?acBRx(A9kSx1a`D zx?50S~gq)$h9vKO<`_zUp?$ zku~N%{jcydvc~D31I4NjZ~88NM%EbqyzkL3WR2DD0X4`P-+utqB6q>p-og4*eR%4f z^aa@i_k$?%0DRhAtS{tZIOlHskL-qX|C)L#!wc@k|HwZ02Vn3i?8ExE5wAUNv;KX8 z%F2H*@<;HDPCH-u3?nO_XJp-5ulwM&uCnfVAL_SR_pfWdvhF)qS@}&P>;B~rz-HF` zf#b{TfgG#rSynvG!*a|cT?kv*eAwms*W9eZedK46->{GTsZ@+n<{XY4eLm#$kS-oF zF3aZL&@PY<*av+HjX3GcvKOGWhTRWW@L9&*h)SuDRkD(F1)s~1^>`-d-H-H1E*r3W zI>j@rQoH}!$MoYVGF;eeB^s!Ijdms08i^PNu-wcSRtw7aSULsl&nU3|Es(V^*MFHw z-4b+~_!mIG)%v@wD!dR74|y%($J#m&K=Q~^S}KKuH1@_fB{<5)z5(`EUn)zWXKufen)XSOr`Yf1PM8!ko?pzm5sJs4s{ z+S@Df9bcRK$n(%o_5ay2&qxdLf#rf;%f{{S}lA_a6wkK9j*-z8htM#JOCiJ!FwA7%fUUZt{&m}&u&s$o`Pkz0;sZT{JwrXiJtIB4dq#W4dSq+vR`=G#gYx z^+tPRy_mbp~P@vB(Xa&nixw+GB@c?<|RGJxygcLVX`<`p7bRflCk9G mWJj_y*_G@|ZcFwj2ao!xhLc4u~G7gxXa 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 literal 0 HcmV?d00001 diff --git a/GUI/AboutBox.Designer.cs b/GUI/AboutBox.Designer.cs new file mode 100644 index 0000000..231a5c8 --- /dev/null +++ b/GUI/AboutBox.Designer.cs @@ -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 . + 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 { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + 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 --git a/GUI/AboutBox.cs b/GUI/AboutBox.cs new file mode 100644 index 0000000..10509f1 --- /dev/null +++ b/GUI/AboutBox.cs @@ -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 . + 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 --git a/GUI/AboutBox.resources b/GUI/AboutBox.resources new file mode 100644 index 0000000000000000000000000000000000000000..5c4f53ccdbc261690b80e111b0060b52061ef31d GIT binary patch literal 4000 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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 + + + \ No newline at end of file diff --git a/GUI/HardwareNode.cs b/GUI/HardwareNode.cs new file mode 100644 index 0000000..e8d0492 --- /dev/null +++ b/GUI/HardwareNode.cs @@ -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 . + 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 typeNodes = new List(); + + 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 --git a/GUI/LicenseBox.resources b/GUI/LicenseBox.resources new file mode 100644 index 0000000000000000000000000000000000000000..16d5a38e0b9ac217e2db04bfdfd3fbdfb6c7ca36 GIT binary patch literal 28675 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 C<$M+Z literal 0 HcmV?d00001 diff --git a/GUI/MainForm.Designer.cs b/GUI/MainForm.Designer.cs new file mode 100644 index 0000000..280b11c --- /dev/null +++ b/GUI/MainForm.Designer.cs @@ -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 . + 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 { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + 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 --git a/GUI/MainForm.cs b/GUI/MainForm.cs new file mode 100644 index 0000000..2f13744 --- /dev/null +++ b/GUI/MainForm.cs @@ -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 . + 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 groupList = new List(); + private TreeModel treeModel; + private IDictionary sensorPlotColors = + new Dictionary(); + private Color[] plotColorPalette; + + public MainForm() { + + InitializeComponent(); + this.Font = SystemFonts.MessageBoxFont; + treeView.Font = SystemFonts.MessageBoxFont; + plotPanel.Font = SystemFonts.MessageBoxFont; + + nodeCheckBox.IsVisibleValueNeeded += + new EventHandler( + nodeCheckBox_IsVisibleValueNeeded); + nodeCheckBox.CheckStateChanged += + new EventHandler(UpdatePlotSelection); + nodeTextBoxText.DrawText += + new EventHandler(nodeTextBoxText_DrawText); + nodeTextBoxValue.DrawText += + new EventHandler(nodeTextBoxText_DrawText); + nodeTextBoxMin.DrawText += + new EventHandler(nodeTextBoxText_DrawText); + nodeTextBoxMax.DrawText += + new EventHandler(nodeTextBoxText_DrawText); + nodeTextBoxLimit.DrawText += + new EventHandler(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 nodesToRemove = new List(); + 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 selected = new List(); + IDictionary colors = new Dictionary(); + 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 groupsToRemove = new List(); + 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 --git a/GUI/MainForm.resources b/GUI/MainForm.resources new file mode 100644 index 0000000000000000000000000000000000000000..7f208cb7d4ee9a14ba7fba17ac674f2e6b1c693b GIT binary patch literal 15841 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 204, 15 + + + 17, 17 + + + 124, 15 + + + 55 + + + + + 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 + + + \ No newline at end of file diff --git a/GUI/PlotPanel.Designer.cs b/GUI/PlotPanel.Designer.cs new file mode 100644 index 0000000..6ceb98e --- /dev/null +++ b/GUI/PlotPanel.Designer.cs @@ -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 . + 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 { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) { + if (disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + 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 --git a/GUI/PlotPanel.cs b/GUI/PlotPanel.cs new file mode 100644 index 0000000..bab52e3 --- /dev/null +++ b/GUI/PlotPanel.cs @@ -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 . + 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 clocks = new List(); + private List temperatures = new List(); + private List fans = new List(); + private IDictionary 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 GetTemperatureGrid() { + + float? minTempNullable = null; + float? maxTempNullable = null; + foreach (ISensor sensor in temperatures) { + IEnumerable 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 grid = new List(countTemp + 1); + for (int i = 0; i <= countTemp; i++) { + grid.Add(minTemp + i * deltaTemp / countTemp); + } + return grid; + } + + private List GetTimeGrid() { + + float maxTime = 5; + if (temperatures.Count > 0) { + IEnumerator 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 grid = new List(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 timeGrid = GetTimeGrid(); + List 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 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 sensors, + IDictionary colors) + { + this.colors = colors; + List clocks = new List(); + List temperatures = new List(); + List fans = new List(); + 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 --git a/GUI/PlotPanel.resources b/GUI/PlotPanel.resources new file mode 100644 index 0000000000000000000000000000000000000000..06c24d06c1cab750788146ce052b37770f3fa530 GIT binary patch literal 180 zcmX?i>is@O1_p+SK%5g?SzMBus~417oL^d$oLUTL1*ImYq!#HY + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GUI/SensorNode.cs b/GUI/SensorNode.cs new file mode 100644 index 0000000..0bc61e7 --- /dev/null +++ b/GUI/SensorNode.cs @@ -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 . + 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 --git a/GUI/TypeNode.cs b/GUI/TypeNode.cs new file mode 100644 index 0000000..2dbc6f9 --- /dev/null +++ b/GUI/TypeNode.cs @@ -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 . + 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 --git a/Hardware/ATI/ADL.cs b/Hardware/ATI/ADL.cs new file mode 100644 index 0000000..b19cea1 --- /dev/null +++ b/Hardware/ATI/ADL.cs @@ -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 . + 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(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 --git a/Hardware/ATI/ATIGPU.cs b/Hardware/ATI/ATIGPU.cs new file mode 100644 index 0000000..81a9af5 --- /dev/null +++ b/Hardware/ATI/ATIGPU.cs @@ -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 . + 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 --git a/Hardware/ATI/ATIGroup.cs b/Hardware/ATI/ATIGroup.cs new file mode 100644 index 0000000..5e57772 --- /dev/null +++ b/Hardware/ATI/ATIGroup.cs @@ -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 . + 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 hardware = new List(); + 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 --git a/Hardware/CPU/AMD10CPU.cs b/Hardware/CPU/AMD10CPU.cs new file mode 100644 index 0000000..0034ced --- /dev/null +++ b/Hardware/CPU/AMD10CPU.cs @@ -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 . + 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 --git a/Hardware/CPU/CPUGroup.cs b/Hardware/CPU/CPUGroup.cs new file mode 100644 index 0000000..3ce39f4 --- /dev/null +++ b/Hardware/CPU/CPUGroup.cs @@ -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 . + 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 hardware = new List(); + + 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 --git a/Hardware/CPU/IntelCPU.cs b/Hardware/CPU/IntelCPU.cs new file mode 100644 index 0000000..f1365bc --- /dev/null +++ b/Hardware/CPU/IntelCPU.cs @@ -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 . + 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 --git a/Hardware/HDD/HDD.cs b/Hardware/HDD/HDD.cs new file mode 100644 index 0000000..f779868 --- /dev/null +++ b/Hardware/HDD/HDD.cs @@ -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 . + 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 --git a/Hardware/HDD/HDDGroup.cs b/Hardware/HDD/HDDGroup.cs new file mode 100644 index 0000000..25d2ac6 --- /dev/null +++ b/Hardware/HDD/HDDGroup.cs @@ -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 . + 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 hardware = new List(); + + 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 --git a/Hardware/HDD/SMART.cs b/Hardware/HDD/SMART.cs new file mode 100644 index 0000000..3ce5676 --- /dev/null +++ b/Hardware/HDD/SMART.cs @@ -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 . + 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 --git a/Hardware/IGroup.cs b/Hardware/IGroup.cs new file mode 100644 index 0000000..e00ddf7 --- /dev/null +++ b/Hardware/IGroup.cs @@ -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 . + 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 --git a/Hardware/IHardware.cs b/Hardware/IHardware.cs new file mode 100644 index 0000000..b2595c7 --- /dev/null +++ b/Hardware/IHardware.cs @@ -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 . + 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 --git a/Hardware/ISensor.cs b/Hardware/ISensor.cs new file mode 100644 index 0000000..2c453ef --- /dev/null +++ b/Hardware/ISensor.cs @@ -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 . + 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 Plot { get; } + } + +} diff --git a/Hardware/LPC/Chip.cs b/Hardware/LPC/Chip.cs new file mode 100644 index 0000000..28f9410 --- /dev/null +++ b/Hardware/LPC/Chip.cs @@ -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 --git a/Hardware/LPC/IT87.cs b/Hardware/LPC/IT87.cs new file mode 100644 index 0000000..b8724b3 --- /dev/null +++ b/Hardware/LPC/IT87.cs @@ -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 . + 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 active = new List(); + 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 --git a/Hardware/LPC/LPCGroup.cs b/Hardware/LPC/LPCGroup.cs new file mode 100644 index 0000000..914884f --- /dev/null +++ b/Hardware/LPC/LPCGroup.cs @@ -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 . + 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 hardware = new List(); + + 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 --git a/Hardware/LPC/W83627DHG.cs b/Hardware/LPC/W83627DHG.cs new file mode 100644 index 0000000..ab06e11 --- /dev/null +++ b/Hardware/LPC/W83627DHG.cs @@ -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 --git a/Hardware/Nvidia/NVAPI.cs b/Hardware/Nvidia/NVAPI.cs new file mode 100644 index 0000000..3cc1223 --- /dev/null +++ b/Hardware/Nvidia/NVAPI.cs @@ -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 . + 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(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 --git a/Hardware/Nvidia/NvidiaGPU.cs b/Hardware/Nvidia/NvidiaGPU.cs new file mode 100644 index 0000000..577d6a9 --- /dev/null +++ b/Hardware/Nvidia/NvidiaGPU.cs @@ -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 . + 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 --git a/Hardware/Nvidia/NvidiaGroup.cs b/Hardware/Nvidia/NvidiaGroup.cs new file mode 100644 index 0000000..74079fa --- /dev/null +++ b/Hardware/Nvidia/NvidiaGroup.cs @@ -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 . + 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 hardware = new List(); + + 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 --git a/Hardware/ReportWriter.cs b/Hardware/ReportWriter.cs new file mode 100644 index 0000000..339c7d1 --- /dev/null +++ b/Hardware/ReportWriter.cs @@ -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 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 --git a/Hardware/SMBIOS/SMBIOSGroup.cs b/Hardware/SMBIOS/SMBIOSGroup.cs new file mode 100644 index 0000000..1d8a417 --- /dev/null +++ b/Hardware/SMBIOS/SMBIOSGroup.cs @@ -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 . + 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 structureList = new List(); + 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 stringsList = new List(); + 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 --git a/Hardware/Sensor.cs b/Hardware/Sensor.cs new file mode 100644 index 0000000..721fad9 --- /dev/null +++ b/Hardware/Sensor.cs @@ -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 . + 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 entries = + new Queue(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 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 --git a/Hardware/TBalancer/TBalancer.cs b/Hardware/TBalancer/TBalancer.cs new file mode 100644 index 0000000..139fc27 --- /dev/null +++ b/Hardware/TBalancer/TBalancer.cs @@ -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 . + 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 active = new List(); + private List deactivating = new List(); + 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 --git a/Hardware/TBalancer/TBalancerGroup.cs b/Hardware/TBalancer/TBalancerGroup.cs new file mode 100644 index 0000000..c37b1f4 --- /dev/null +++ b/Hardware/TBalancer/TBalancerGroup.cs @@ -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 . + 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 hardware = new List(); + + 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 --git a/Hardware/WinRing0.cs b/Hardware/WinRing0.cs new file mode 100644 index 0000000..ec0baed --- /dev/null +++ b/Hardware/WinRing0.cs @@ -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 . + 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(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 --git a/Licenses/Aga.Controls.License.txt b/Licenses/Aga.Controls.License.txt new file mode 100644 index 0000000..00a76f1 --- /dev/null +++ b/Licenses/Aga.Controls.License.txt @@ -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 --git a/Licenses/OpenHardwareMonitor.License.txt b/Licenses/OpenHardwareMonitor.License.txt new file mode 100644 index 0000000..7a45bfe --- /dev/null +++ b/Licenses/OpenHardwareMonitor.License.txt @@ -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 --git a/Licenses/WinRing0.License.txt b/Licenses/WinRing0.License.txt new file mode 100644 index 0000000..20b0886 --- /dev/null +++ b/Licenses/WinRing0.License.txt @@ -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 --git a/OpenHardwareMonitor.csproj b/OpenHardwareMonitor.csproj new file mode 100644 index 0000000..71fbd77 --- /dev/null +++ b/OpenHardwareMonitor.csproj @@ -0,0 +1,148 @@ + + + + Debug + AnyCPU + {F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880} + 9.0.21022 + 2.0 + WinExe + false + OpenHardwareMonitor + v2.0 + 512 + OpenHardwareMonitor + Resources\icon.ico + + + true + full + false + Bin\Debug\ + TRACE;DEBUG + prompt + 4 + false + + + none + true + Bin\Release\ + TRACE + prompt + 4 + false + + + bin\Merge\ + TRACE + true + AnyCPU + false + prompt + Module + + + + False + External\Aga.Controls.dll + + + + + + + + + + + + + + + + + + + + + + Form + + + AboutBox.cs + + + + + + + + + + + + + + + Form + + + MainForm.cs + + + + + + + UserControl + + + PlotPanel.cs + + + + + + + + + + + + + AboutBox.cs + + + MainForm.cs + + + PlotPanel.cs + + + + + + + + + + + + + + + + + + + + + + + + + copy "$(ProjectDir)External\*.*" "$(TargetDir)" +copy "$(ProjectDir)Licenses\*.*" "$(TargetDir)" + + \ No newline at end of file diff --git a/OpenHardwareMonitor.sln b/OpenHardwareMonitor.sln new file mode 100644 index 0000000..9a14b10 --- /dev/null +++ b/OpenHardwareMonitor.sln @@ -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 --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..1734f70 --- /dev/null +++ b/Program.cs @@ -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 . + 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 { + /// + /// The main entry point for the application. + /// + [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 --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ff323b9 --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -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 --git a/Resources/ati.png b/Resources/ati.png new file mode 100644 index 0000000000000000000000000000000000000000..6ee6ba1cacd99fc1f8fd0534f25173e0ca69ed2f GIT binary patch literal 937 zcmV;a16KTrP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXiC z5F{Yt&o7Yx000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}00097Nklkw?3`ZvX35l0i&t zBjU(1ier*NpL*>K&1RFc%_c=r&^84AWmjlP z3#ovXfzTLIG|$mA70P8DY;H0UMKavo)&Aijg>z&{!VsiXsj3km z02sx*zP~S~*_3#8788bKKmsUGh%f|ks#2(u0ztKcZ%_=%{N5hH?5y@04I1m~sI{b? zM*+86s zCA=q3XwJ<^rPI+y?F>hcew88ske_bdD&AjR6+q)L>KIvK(D4LG zKu6Qv>OC{k~7 za`Mi>!GYi$*=Qv3V8CBbpHi>YPx#24YJ`L;x57FaROJ(US52000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igG% z5dk<8_CX>@2HM@dakSAh-}0006RNkl@3%2^<}xdnV=Hk(jmpa065Am<#15{ce+DIFL9q^9ItaTZv`YlR zckGgO@*reV9U_PfO;|w;(Prf$X6+OIkWAY5zHf(5caYh0c;S7X_j#YoBaS3405c;o zG9v*oBQX)1#K=qpNQ4ZCgbYXu7*ti6l+rhuuXR?r_tnR)-B>V;GsAHl`huMv0FVII z{F_?Tm`Ew9Y_@ENE7>AOoU;pt0RTd3w|lO_1{y0p@s3_V(%2-SNlhxL>@YARm5QFd z9PR4XgwR*VK!~EJ|J`FE(wOMsiCfLpUQKHD>j#AppfN}dKnUQ<(G}mg4FGo7w+)=T z2PTU{@o2dD*xc;g`LOiCo02oQ`Y_0F_zLWcwb^YRiKTxx~#_RQzIV(b;;Obib zXnU)p+<_5yLwVh$vh8>7P5t@4JepRFJk*saYLA}W z-*o*oJAZml-OGPx#24YJ`L;z|4Y5;1&<`N?S000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igG& z5(X3C>dkuq00PuWL_t(I%e|A&YZP}F#-DfQJ2N}8o9vV{VO@VjgEXaG=w;1eZ>bPT zNR$}cSW+Yql0$DPB&>xT`UmvXOG6bzR!SfVW;H%~Gf9_*#>>E-3&^YHNU0RPvVKcC+JdZmBg)pv<|dwZ!|F2k}crBo`}LI|g= z?W1p_jZG(3S07&duqm$YIy-U?U~q6yDV0jHUau>eOs2uM?Y}+G`!114ARLa!0|yQr z428_Dm6ZnLCBySpft|Dg8vcGPOM8OGQbo10tRjEFdZ2&(XrKKf$128r=Mssts(|2y)dtw?k?C1xm@BDS^ z$QL70(Y)*K0-AbW|YuPgg4MovLlm4}lyMFNE+OI#yLobz*Y zQ}ap~oQqNuOHxx5$}>wc6x=<11Hv2m#DR+Tdb&77eTiH;a^yONTfM=4v>1@HiKa)$c)z;6vW4I!% z=y*cepZ3OAhO-Wx>SpkWV*SXWerdUhfYj?EPaB4w(&K{X8ZXp8mAKKR$G&gFbBAva p*hE&DGVeEu`lA0YYK7}Z#x=DLUe!5P9YBvTc)I$ztaD0e0s!V_eq8_n literal 0 HcmV?d00001 diff --git a/Resources/computer.png b/Resources/computer.png new file mode 100644 index 0000000000000000000000000000000000000000..495156c61f2e2bcfef08d8a1f4ef97116f873d7e GIT binary patch literal 576 zcmV-G0>AxPx#24YJ`L;!67jR4Pj*I#h}000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igG% z5fu;!|IFk7000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0004-Nkl?k^3#{Am%zi5{Th~D z2HtxB)FP?@(STS$47>!?KsBHm8ft2Qa}KqLw}7`;fg&OSvxul68u1qY3`o-y)mV8z zG?s2vY!RsxBuP>OvTd4J*peTsJmSp|DIqFNK)MZRoUG+$v4BcMEBKWyBuTO*Ga_Q8 zk}B6azCwZbzMisJK&_Ho&B1FqSo!T1>KP0M1E%+{@AQ!R{eBZL9v_@mFKcJJdF#fb zr_Uaft=H@Q*RS48U%Y&dbB^I~$ZEA}^a(H;jd0EZuv{(yp3J_@ez;Dnw?2P=Mz7bS z+wG#NbUGc{?RLXAn+-)#P!t8NR*U@mjD+l7c62y72HyV5S3WwN9RC7fFf1BK(E3;a O0000Px#24YJ`L;yqpasXvMoopWf000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igG! z5-2ruHvSR-000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0005LNklGg4B-0k{Lc1s8x7B#;o83lJkYKsICu zZ2~eetEv8}BIv;$<28sUm0GImdU~&_Tb}Ojx|KpyMWdn`iG677`crFNBS{sF5mjaN zb462f=F9aBLbwPaaPa0GYazgfFu8x{ICc1Hk0z=TMw^83h!6s|9zVp2QF5ZBjHN_L zg`5%=6FDdFN?@hXXs1XBgfL<>9`(hHTfjm+x^s7+ zz-Uw><6LkDk#bzz-oD3lI%T>1%6z`Xi^cOZgl0~oT}Mb6F+&C}XR{ecN8f4NmQRNV zlzdiEuRytwGh(4{Zva>Nn*R4iu@so~DG2RmTY z?UZt^0yCqDosv_k{zd8wa89l3TmpBRPPOmx`n3K7=2rj05Z^w0{A<(X_RUi>koRwI x_@gI=yJ6;-8*WZ<$E^%Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXiB z4haBPkG!b>000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000B7NklF{aaTZ6KfVksjS2BU#n z-)Vs*KOf8tS(62oN`lkrL}+Rn!?&+v5!raMFX5M4w@`7g0&cgPlSu`5z2StYu6b3I zI?Ki7s~v)wg~M4cjOKjdC_5yoJT<~*%@ZoEQ8YH47PG;iU}kau{sU1~ULjP6D_xh< z=?o>4NeqvSz?74Nrluz9@BIr7yM?k15`~tdIDhT}eewBc2nIt4J${VxGAAvDmq1@# z`dW-nOkjF?202C}R-+p@T73u&4K>Kkw;`QLV{?5D4=(Bb3dM8P(QbVmI z6gV6Xbp7!g{QdwUD^JkfbrbXR^Dr6<01yKHNi-Zkj*5e?0VMFKuOE>}1Uj7#>aFb^ zoI8Jk6(xz>++6r31DFo@*kIJdQ&SIFmND%c!JWIkY_%T1(O0VR-|zr#|NJWl0)D8& zOJOLALj8UJun+=zy#ZOWmWqnXx#!OBv>shY-LXbil)q_ZHNxNj@FQ|eCUkaOp|fW{ zVQFb;8CtD|i(ar|e?JYaMuUqNKjr4;Gr0F)oco7^eDY)?PB%AlA|8j)Xu#aU96tE) zBMt^iS5$h&=49=y#=*O1$T7~#=H~IYP66DD6zi;o6QER)r$7kR(QQ$O!@<) z(P*J20%@{j_4l%NQDI! z7z{e18#itWpWjD`-2}%I321d16k04`CdA`0I2;aa@5B%ahA=xj1CmsbWf?lHhFq@0 Z{6EyEwvCX*`5OQL002ovPDHLkV1iD_;;R4v literal 0 HcmV?d00001 diff --git a/Resources/hdd.png b/Resources/hdd.png new file mode 100644 index 0000000000000000000000000000000000000000..6f704785ddf58df34e9c39c24d98101c641d49b5 GIT binary patch literal 649 zcmV;40(Sk0P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igG@ z6b=lj%yIny00Id~L_t(I%f*wiY8ycqgunIOa*~ZCeB!Xdg(A?kc9&pq?Ovn~#vn-Q zG$9WWaNfYF@(508zd#y2fHoK$BGza2Y;-5@?rn-#f}~34fuDb-nZKC%;khAJWH=nY zJU%}Dw!6E#4G=zkXKUzeAcuar_h0OFOw-rnAuv$L~pV+>MCoO3J|3-0dj zaL!?jA%sAl=R4Es^qo@bBS7?Yy)_<>zwGbtx7+PDaUA2EqpB*lwzf#qlq5;0stT<& z*4q5~`ucNOmdyr$5aRX8$;q}5g1WBJT4Ri%+wHQsxrs4`vMdQ9P*oL2M@KtS$}zwO zz~SNH#5sqQlKFg26h-uUJ-qi6MS(Gfx~_4~k>@%6exHMbgSPCX-J>2vL?L zqtS>~tA#O!qA0k(zbAx1mStpFhEj^6C}_1>FJ`mZS1}w8-(Ou_eX8pkr4&L4vMi(9 z?XIJGe0*d+pQE+Ld(U7npss69PftI@KxeU7Fq_S=*5aJw_VyO%9L_ncwODKM-eaw$ zX&RJLq-jdiH0>BbYt6;Q1zKx*y&j!Tha^deq6qIjaU8F^;JwFtPg$0%d*Hn%O;e5y!U_cfAw;?Ts}NJOvO`_eP9Pj j{__PaV1S>`{*3$v+vhiDD!2%S00000NkvXXu0mjfVo@uA literal 0 HcmV?d00001 diff --git a/Resources/icon.ico b/Resources/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..7aa15e69e51a33ae3fff5ba0647d7bc8e33d568c GIT binary patch literal 15342 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 U|DjPXO8xcOGC%y0KdtZoFR|M$OaK4? literal 0 HcmV?d00001 diff --git a/Resources/icon.xcf b/Resources/icon.xcf new file mode 100644 index 0000000000000000000000000000000000000000..79c7dc2fec83c352414b8d14842f10bf5628ebfd GIT binary patch literal 44594 zcmeHw2bfev*7mL2Jp(f^%m719LvY9g%#dNoSu(has0<(?CJ;ePFs_P9fz9JvXbBytSV@bK2CbjyWCWb)1V%_Eu|< zPCE{%yPx&r7bLypqB&Ei&$?h{Rwp+WzP$8!U)t~5&%a>SysTLlOh0?ZMWmm7)>#+L zm=`ce>SMpsZxTr<2m3OcJTK%!;%z)HxtZss{t6nI;(57GdETIUo;Us*&wJ<$&wJ(` zC0M@N5*FZ{2c=(i^o#{rBd18h4!* zckTMZSMsWaGsob&GnsC3M^64#_PPM?JkZv^7sp{-^HrdS|3`fH9*!???BI>U3@@5+ zRL19jbcAs~?m!nE?ZNH}>~WNwy6~QpQxjbOv*koLb8-@ABm>a>Gx{Fz2|0!S1aUP^ z{64e|-|xW@!M$p{mmnj`>>tU9_u^#4Yjp7wuq?BB_$J_pxV_)~jP zfOj5{Q}}zZRvXuR73h%!UXvcc0Xs`3-(F$rlV1Auv%Qq-yWp7bRl9x;K6jAs(yqS{ z?}h&GU%pioBStY|6eC74ViY6dyR;}qjLL}S6VF`V2*>I6y)fx!ukh!78$}OM^dRrj z10)Drh#im=^c@@!$xqOG9!2N$PFwkB>z(5{y#x2$EBQlvRe*OMm`U>A0AC|;%~ydQ z$?%Ix@QX@20CTCl0slxmDA@-gtq1FQW+C1eHa+&Ud=F{Ldtun>V=-DU2GuOQ&jQua zpXGZ{$$LPRhSq7IO2vCBsE+uQXXvPJ`{!uy+U@hm>n%f zM~l(XVsx|^9nC^Vi_sC@lNY0-#pq};I+}%!X0fBi=tw^V9i_3OG<1}Pj?&Ok8ahfv zM``E?@5yQCC=DH@p`%oEl**3M(2;%!I*PKRC_0LwqbNFxqN6A}ilQUDCr8my6dgs; zQ4}3T*-;c7=?Ce^{90zpsq0bwsLx})JqtZ=Vd9Z?ye|vQT6ih?!-Qi8`b+qX{$_dJ zti%KTC4RvML4TMx=dK6(3$FPc`h!)cCLZW7@e4Kx`or`o0zJ@QaLw<~AG|u6c%Z+; zFW7+n;q?3NvbuNqwaP3*=RRGY?=!6~u{}6L8H}fgV-Ba5dyr)!#(|yNWjo zlTU*keOq39aPQ9TUvJsCVeRTazq8_%KRo};;}0#nYw685EcWV(A;QRdLyGydwtv$!PB=qea+Kfc-q3#CZ4|ZTEtKA`|V$E{W5NX z5C3Z>SVq>4H^IHU5u4ynemvd;xAMkuC%EJ5Ei%EkSG@X%7oK_i;bnKm>tVDo6b|1m54etpG)i@Zi&`J8jl##>|tP8HM6 z;N@vNP2%Zfo+k1%o~JQ9jpFGgr|W#_2;P%PrZ5S$x}C;y6}|u&pFj`let7E zbKXpjBa@kaIxl~8GGlpHCNqLpvB?bL$D=0GgWvtnO-40y;dybI`KgmRN;AisOiVMK zIjw)HW2xXP-NB+Ub)fjy-Y6fc)-V^1^wA$^C+kJ|(qu^l@BAZ@xM&_F*GY-y(a2GhoamlsU{JIb=>v$W# z`0Ug5>(+eu!F%tzUY}e3)Dw?B^uV%v*z~3)*Db!PaN%Way79};KmBCwN2}j|_fIR| zeB;$W{^7;vpCtni+;`7ix8HWlO*dS3%~e-w(@h&cCktTqPw%|NroRKPPk`5D_uhTS zZMXd9hU*t!edWT-+3S`~Uw*!U-M;rOn!XNZpMUO|Cm(y{A!(}9x^j^;-MVSx7aP_K z2k)#D5pZ6QKl&i%1qs|t3D{n@ZT{-Z&(^P9^C6gh`^`6AdHD}7qUjTls0h$>356xS z{$&fAehOwk_%oWm{wkZQ2=2S*j-?3<{ADYc{S@NDywEE}fToX&VA0eHHs}>i<9nqD zz`(tC-+4O)3mqr}+aQ9^s00x#82G*P8t{syR4j$Hb@NwWa9XS1`!jSvBM=F=roV}s z)|Sl>mX+(u6|cSW5}Q6rUSsBBg@sPR>e`Rg2w*S2fBrcr_K^f_DX&!QCm5dspkkq| zXRTsk1GnCEhE88Rzw9SfNNoVnbqZ&Pz4{a`4BBR{EFB9s809m zufPS+DJRAGJ8PvEvZ?uC(|dnj1(B}6@X!=J`*C)94{Sx;#x5G z=R-^O2?T%x!v2I)b_!K3n0FzYzW&;)ul(^P_W9g$VH6O=If?k;0O0hJ`4>skSN{0& z%Q86n1XexrkPLr2hQDzMF$j{nc;4JO?DgfBUi!oDUVQ$!XP*I|k3B-=bM~AQ)z3~Z zzUaaW(A4~XlQiVuXo)@nYj*$wVJMI(rZ1hc>BbjdK#$9x!QhW$bnq!HgW<2Zl$>60 z9-BV@tTu$?A9gJvd@#D0bD~V=&OZNKHbsX|KlLQKd>Dgc?i?L`-auUE@C)W&H0Ofz z&Oy@(G&4_Zee6+8=mGF~_np!dbGp{b^x}CJqSv$8EoOsu82tWam=PuqgF;J;uhYl) z7o0b1CYpZr=p$efJ)$9IbUR#+a=I3rE?RimB?}-^jDPkF8;ghn@EDjEY)0_iB8Ej` zMi|5*i7yNq7BHM|0khQ%7>g7JK9{yG!o4Io_yk}8VT+I%7hoh7eJnVn3@{dHfVt}q zK@3bU7K@140`D3PwJB_taZ_WFFutK*dcM)CnL;F@mR zg5-g*=>2!q2&gUzFq{_gHE62Bk^sY|Dl8-!kqXf6PFo8>Sek^raUi(VZd#6t2Ki$yjV zSYwf}X=BkM7mGeZgu(EPn%b!q6^+Hk0*ytCgos6q8!s~&1`r2VAaeW>C{Od(_$nC|F_x2Bco}dLP0fl;3^6YUEhT8* zbJy*nsUQ|HY?;?KF%}_k#Kj_jEbtI$p`F@TWL_~ZZvmT_yTmt%26wAW3Gr7hydo|Z zF%BYRB5+9DfSoWCxCN<@1Ovn(z&59a4%rZ~h*1j?1#%OPWq6tXg86`LHg&Oxfdeh2 zPqxJDMNy2JfNeHKhwM=UAq488)(zLmoFu@-$0A0KxLBmY04ilB62zj7Pd|yFW1)zA zN_b_^Ty*(m3lLvtBWjR=Cms(P-m5|DmYW&huAxP7_6UXNopV$uLLj^|E@(lcGCbmI zEEF+$`_tP1((AGMP z@wV2HsC85*5@sc8vDji|_>5pCg2wHd4cG$aFI!MSNWsavOhb{R`p|)51{siAXPee# zQWnKG)e2nDfV9G49cHf@Nv+JanR zxGrw9hGo>Sp$M|FinXB#3AC$BQ5GS&W57Z_DE6nR# z7-4?T0E1v4Wf3}MUE(SjWZUeOJ-SeYdP55+y2>%3Xd`;mvIwCFErU=bv4CLANx8BJ zq3A^|i`Y`iA{m}KrBS)EXd|K^8`@9=iE3FC%;^e&Z5N7cm#kspLlFf9gh$l4@PhL> zEy$AflZGM`J1jR)><|GlJQXDc44W>0MhdO?Py~rWP7<_Ozp~b1S!ABt#8AW{27@CD zfSBOX3@|c0A|V2dgd+3!rpF#-<%nX(g(8lAEm8G~%Oqx>f38$T=F!cpidd2*R7DJ0 z3om0Nlu&dQtD=fYE2B-L^}NVU(dJRC6ic(e8Y0a%*S0KVbIi~SY{*oDwfn_)>&jysPt0G?3wZ{tzg#KXR?9J;Vix6uruTm zwevYMXG~)Qq)xNWI#VubI%iFv%5PaP&zLqvF3+8XFXa-c%Z%v-a)~d`oH|7=XPwP2 zd0BQgzcf?odS%j(SLJ6-pEkwk#hKHl+KZ_La-mv+JkM7xF^vkeBw121WDy7}PGMq_ zfj*pS7Q`zori6Hf&2_p%+v6!L=;4z2^NusHXi5C57)E7XO)fR7E0$bPwIoIrC=3c! zg^6zEQcPy1Qw;)hh^h zfivOqSP!B??6+7j3v?5A8PiR|5Kxn~guu7sok`q6m_)aL0VdycCLpR@(v;3UTQ9}d zoNnkLY%7dgHGv8e<+nr>*gY?$D|bo1u+9XH$2rq1}MtB};U9 zwd)ftS*u}qcwJr3EZr>4F!T)!xWXj@DWfwQf=^X(J#VY@cGHdQZ}BxUGD7o$`EV?m zIop{jx|eDmG7p;jw@Hjf+(%U{Y%rI#OQ!-16xPNE?!SK-qdpP@5tbE!2+JlOfOi^i zoUl{|H$VZ`FhfBuMX?fh)QtVRH{W$9N9NFhtT;HZ@3Y08Oyaa zEXoQZpt-;Vt;?Hx%w6WrZLk*z3x-AgUMUkB?t}xWgD<+01j76pj5!-~Ol%p$5KRl&E zLKTU^Q%De*R-m0$fRgdYjzu!py|#2n27Dv1#bA!0XCY7#u`tw=d(810>7((P2cOcf zHfZkbIaw3Vo_gl&13*<0$hG_}08Cfy60u-_yU_CqGs3mM<{L!oek zB!1!h5rcX9#`q>w8cs?|POjuvs#iHw$t0VkvTz7L7^#HY2T78YT&Z$ON@{8qQ>9K- zzY3ljO)05dDLE+|@{;ibALH+1o60GvRnw}aXJk~bUZZvmQ{7}7POp|$H8rJjauOb( zV7vXHaB`)TDrxB%H8N|}u2a|4tyRyjd#FzBTA4L6($lJ>RKjzVY`8as{;H&9)TmXb ze#6F1vYIwC&1yFHn;mSL)ueI5`gLm6$VjW=g}~tVekiF@O4allwd*y?YM$M?ZM*h4 z9XfQZ(b04`kkh_h+t%65vl`W_T_YW>joImg1GKJLw_(%lHaWRny7lPQJ3qfqjXoy- zK<{2Xx^>CTX_MWwVcnXZkLG`8^U77yGwU^J(WYb9Ui}6R9e(1-QKLtX$rxis?;kbt z#Nk5+_UqNPW7`%@@VJ~(Bvqby~(WGj)H#l+!1l zGI7j^LHS*BvYUWnyAh7kYSe9#-JyH`;o~PwnKA49*%w|kZ{GZj`DWgJBJ!*mQznfc z-oJZ?Y#6UGJ22(SRWfQdY?0G_z^Ic8X3be}#g$htzV^E7mt-t4*Y5{dUU|iWIkO5* z9yOqQj*x8kG3~S(^_sTr(tp&XGiP6V)smZ+-g(cx_bpp?fBOA<8EEfZdh?R2E}ebm zq*495C`~9_DK))TqwG%kBTk+%chQpD?tSR-r& zxid~4fd{C)Z!j5fR=rMEo2~=LPo1;q#=9PV`o))DTk+P)x8Hsz{hhsUV?_Z^55{u1eg2iVR=xk>nvd76U6;NNOFLLETlLl}&p&$C zl1pbz8UY73oK3aNhS|CO#uQw5)ol+y|N5#AKl$v-uQqMoyd{0hC!056q3@FqSH1rH z!?#^^VZj(ng2^;))n(Ac84H%&`}8ZT)_k^U+t=TGyM6nP^d0NBfBVhX+ctf+X4NZC z-@9bNjEPEu`PXjJrrXd{&bi{|hhBW^!ws9i-u~V9yMEZ6v3vawyT1Q!``4Q{eE8Oj z58ZslIj2~PDj9XM+VvPd`TQ%FKK}Bmbzgn`_g#DT?LTlZ3AAKU{R^z}{Wkw{Cd6v-&lUn z;<-}-ih9jDBKdvndkzkR>&(2h+p;=reliyz7@ezjE!SZ+|#&xTLJSB9aj?6&uP*4j=g8+f8d%KELexc~cW8 z#!Q{RWZ4VHr`W!E?b|ObTQc8LRMs&_asLZ%uiLzR_rW8j7$TYxHIWVFrAH3#-oAO= z+b`U|Wd1ZALnu1-88hw2DRyjG_x6kN6gBEKw-hhFy>81686y%u1}NV7F^YHo0mTg$ z2VBLC@gIuv<4E^EvP!C4HO@+Yz9s%BMWVHf*ZvHTvVQ(Ey!K}!1M%wTp^rnjQB#O; zD}D^&Rs;y=gCgT+p{P*&T%`W-Xzp#Nq*V9b9f?+DVH6C}Nvdd`KHEd2E~%x-STxM44g!E1iK@RAG9nX2i{F*($T z@uwD?bA`%4uG|Mw%t}`sHRf%&dmKN$m~l(yB3t?WdvL+BB)nuH@eE zp6#;gWK^-APVCjbDf-1Qq#M~gr&;XN===`N>)~FK+#B78pQ_qVWAqb-C*7Dn9h=vy zQT6}RPa+pP_e3crN^q2wuF5P?@`+j*+C5%liP}umbfOiAkx&h4Ge?rX9&e@apPU)1F($E)S5#1;D)DE>3O z)~3+A#w+yR4UR;dNr0euY>LOMI4FzZn?pPcfP#g_8_1Q2miFLvfj!{tUTW~?Bk%zb zDLPy;p#D9=JE?OZ+hm9P%o_8ONZ5o;TuE zz!m;B$@sp!Q|RB|nMMA>wO3q*S%3-vsk*K_2IhqZ8x&2OB~KQDI1 zmL9%2muGVhc*X7+KF^Xfwq0Pr2RQc}ESX}Fy#T_Vd@8gA zVUMGhh7TJ$c+kN9{rcup*8ajZixvu@QxX??&zvqwntbXcOE-GdiB?I_t`J(q#HlA< zUB@a))P)E3!FIf&@F*g_Q57X9Y97CzFK1Phs>mwpLf-wyii%fPoT4hQqXyb@^c+)_ znF+z9(&4X{^{YcdkuN-W}ppE#E zIRpHiakOfj4|R#Acs%$!^naft4}Wo>pSQDDkM7;NcFyh8u>%*1TeUo)MRTk#!$NlU z?9r`jm%Q9g9k7Jlrd7-A6Ph<`n$_5A=v6dn#B-yDa&8biH&%*RuEBH7>O9wwbM*{f>p8s|uk~Cljn`>aW9O<>cwHq`&M7>n zR^~Z{XH&V6S5Y~cpDQKtjP-b&lfpb>4L>+z%^%mu13_c(yF>#qonuASvwOELo%3=# z=H#?%ONmfajYU+DVHXGyqH5cwHE%R)+C)Uvn4&U`Fu00KMI>iaAK%s&0sWYm>Zq7R zKtEYbCLR683#pn4NyHN`q|~E@RDrz*Oun+5e~Oqw6jQ|KuQ_9KGCg;7@7lF<9!x5y zT^li}X3eZgb?;7->e!Jc1v$Z_u$RFx6HH1BD^60@nCi!wl$Dqm(?2$;nrc#VR+GX$ z2u94%vzn9`lbVz@ER~iTQ@lxu%*3RuoUF9Ow35Y~)TrW3OO5Kd(y9eusTFMmVEK1C zQt&s>Dkh&wfSo*v=Sio;oqxsaljF|6I*H$$G%gnlKt75MXFjD9ja<+)%;Neu6 z?Wu9IJ>_J6Z)Yp>JUM>06L@#xF|*Zq+VdE;k=a&^9>r^&ubg$hnh_wh_kf2HqKM`e zw6mHtYS^G&-8!{0YgVtGo(8T{@E5x(LsBCo%EGyRq5RnI5Me2>*`{7lEne65akzOh+5{UQT`ny6oaWI&BW zUYRe|1g=HDDcGmwe37Uk!zCf+%ecqrX5${9s5v0J5e&o4x2kO0hV6WR>AzGY?j>RR&C*e(ub< zv*%xMCO-YkN?D(S>ubUd_M!mqJW$F`c*OG_a?cak?s(#ngM?QJphkB`T4zj_w3mNhQjD>I`0v4L5y$Tu3Z~oLaUb1%F)QM zp=PK*Br!6F{aSwFrxv-9I|Z0 zi6fNQ428siIcDGBtiub;-~nLk0`=cko4#mI}I? zoo#MM)A6tqmWXPkf1*Fa4Bvnv29zj&Ff62O=L;!|nDSIiP!Ay+gPKuhq&d-yhzuWQ zhJDUqb;6?E-iQvW+^(G|VwJEX4S}?b9D~vf-3Ur6DOR~uE$1q7QbOWw8;%K}9_7X@ z0pM^@Gid8TF$~aRR0=teu~-F(LFs6GzuVc8Wtl8AD{>NQf6Q7AEGil{l(d5&VvMU27BLAS z^$I(*{F-t8*kV?fpv0&ft%L^*ASIS;oPguU)S0dxKW^MuF7c3-xGajLUSSWkCJL!r zHyS^=#hC5e!}!VU_{g}iX6z=+SB9maXic$Y=mr_N>0~;T=uAmF!HhR!&6xGV zGG#25NNeI$Eh&vDCL_!5#0gj>0mA_$QU#1E3|k@5*}Kq`gkhkB@;mXP3FC!Sr)o{Y zx}8o{3|MB`30fse$V?sO7?IL&Qp!vzqu7|RByh_y5%iUE$4Qo5>PC#16Q$quGyP1T zzf-Fw-vXb3a6vhdG7_zd1%pz3RefCSS3OnW5O$<0 zEy9>0BCKzikzb6kgCbPZ21Ta<3^OGYb8s?(PRIQ)c8tzcWQ3X0X*g5U+w|H+OF}^+ zP6JXWBs0-WI7r2acrhrjc#F`2m;$B|QZqt|;?4pv?P#JIUruW2%pj9DZ^(^q2 zIOrFp>RiiYre^Gyfod!%r)r%>Muq7^smRAnj%in6P2V49#vliTl+1`P)qKVB1A{<5 z1PNOkl(`D9Sf??g%gL@8K}_2mC`W7w79q51`eKDv#Bg$d^m?7Apc03qj7WzFDKes? zGRCR((tHm?K`($QY5s7B-WtT8w3mL zlrBTc3Q-D}6|)z$h~2A$Yd{Zxn=V6hKx|BjuBOGyi19;;)gNPlZk{@(Kgu5&p;R{w zv(BxP40sjy7Nsy6w>Ry}Q2mlye^dz3$qfHYuwFros)TTuc?j5BGqA=dWFZ7K3F8}( zK-hq&)*}!`g{Tp9LLorpq;NQ%j^+<5r?oO~F#W|#^7jeg_8=Mg?1TVpa*9Fc0;#a+ z4~q;PVupNSqp0-~A+<8qFe*6YD2G=7XPK)Q<{JYUSEzr}=WpU*Vsx-rHFl>-jo!mU zLRQZ4n3rwlBpDsl00M5Q4o;G@WC#wCPk)F%xYz}4)7Rt^3${BW7Z0IJTj5AfWrl^o zr5Q}gL4!a0wmegREzF)BQUQMk*T)$n3Fo zOG&AQ3=Q7kkMTnN{IdhQnlP@@Cbbub;ub&jUBX=Sn_ zLO7tJzf}e}^+k`SXR)P3UT*S=DIM}^+8u7&x($ZZF^fS6KKu1GeM5MwQ;BiVo*1oW1h*|XG54ZgVrrg%L-8 z+GVdL6blkM)2&qEfn-8OqE0ac4mmtbB%u9$p;5$PkEW>1zMMAW-HV9j+fl!C9!7hI zc=MUHi=}Pe8L`iA7?4v0tAPA07J}3cv0N+lHKrY>*UN~wG zcuTk46s~$FoJ=5yl%rh*utD-CW)-o7&)Py_1;9bc?P!0LluG2+AF>IA47EC@vmqH0 zA`(1MIy1({m|wg7JtZ& zNYewSSc)5C#*|9TMC=2?(+CBP`hAlS-!-CGb~POtXU3LFyhUp8IrDG{V-yjiAA}oA z|E-4#ykpqN_;Hf&1(gHxQ_&3I`T!Pos2Q8^na&3V{w#=5FXPR)k2P1++?M02>1)DA zQtRT@j%?MjI>=C6QsO8X%mnH+eNxC3_=8F@=3kMD2epnXbzE8uuK~1}9=kE9O*4r` zj1VBjpf;h_G#+A-QRC_>ohl_P5C}I_N?QPo9qo!FDa~kvR=`e3mQqYf#$+xIekGyC z3Zb3=Y$q?t~*1P9`Z*r2FI#^e&C zOmy{0R0~DKd{M@fiK?S&*mvAgL^1ob3e{qTwjlN=)r#|Q&Haff&cQ{Yk%{BY_>Zk{ zwW5PYX+{!;iM=vW2v>lN84;rkCR(D*qE`77X|ZV3T9M+4;3w^m(90A)MjDv_XCpw^ zgj%wHfG=lirAuRAvWcZ*J5?POMY=zBtyN3Bhby6Fmz0<)L$F2|@GIs0`e1250Mwch zXl15B$)RS1H7e6KLQpbeBP`0+1*Nvw5tj7TOLeN&kgR|mu=to}gq78&Rxz+$f-lV; z*1!}{grusm`Hdi9*=W{sTxt4L4N$7|0JeqFB^-<~)*i@jgljgDkt~o#?6P6Tg$g3K zq$^0tN<>af%a2F`iM4%dcGO6js2TC8NXf1ah+2i%DMzeH(;R3=Qe<$uQMsiZ4YuJ) z#^g+6Q%{6?R(SIdYU?Y<{i_NLx zGC*CKl^n$%VhfK0K~g1NW_o-Vla7!w#bF-DNe&yT>6lbkSV=Bbd#7x+i)`$e7K%hT zT6_!*N#4jp2YI>a=Obe+gWVA{izKzCXLm%7%ruVqf>r@$NZ8d6#TvLZZ~P`uBavFi zvvg8>7?ekVN}3xpRa-%r{DYzkb!*1`Jxbi(l@OAy1|@_+O23gpbvm?`&bShrqm&*@ z=9w3V29#)4j)G;kB@4_3teQ^6&Q?vEQs(lKAcHQ{zq~KpkyQXC(-SG!A=QNr2lo*0 zqOF=%<(6M<4`CEl6@8RZDIS!}bS)J!%y3VK0P>(l6dhVRNFf;-dD^sW$8EAZD}9!TiCSWBl3_%%UZ@wYDegET&ZocOXLIVQ%Mx)!hz-Ssf8NRrxZ( zz9;y85Bzhm`95{l15hfT=xnHC+#@ zc9@u$_NHyQqKFw8($$uIZk3ucV)(Ui|F2Hn6Pc_=wU5E9u+J=ean%l}6Gii0ygj`XL05THMI@q&`o74_P zF8@bTVupRI93MBz!?}x9o#c3bTw06-476gt+gv!ZJQI$nQ>?s^7RmvwnXu0>Eg2*B z9b^NIz{^$Y{O=_E#WsZm9F(@4`M4QZ!n7I>#F`O@Ty~6<9MN+Jo^o(zp#xiFk%1>} zb!^K%is*JA3J{RMuJbup2e{IXbwIFH;?RL`6!X>u zZq394PA#Lj=LTakL$=cViDfq3jHQegRm7C`1T`V;AA@p5_K=W@bYcv)ty0;_XYm;0tK^@eY0}!+vtK1mXjK@xZ zt0!gKLd=1%299Zil3G*3HfKO7pk=H-ZjBJqX;h_ynW+Y)C?5Y%Pj{N3HE_(;W0lwV zIzWphh}WhZs?*qz>TZXyXW`_-jdCnEZFX=7Qbr3k2RBiR_nau!V5EXDBR)&aypON+Ylov01C)DuvDtgAD97Kt;Z;-_^A_;2>>r{rRm=esdHxPDHV*(1G0(K3s zvW%1kNhh4dN9p4C5B2r){~}He^AV_~{RChlJTjpVW1%|)Nq)l$Ng-Mj^8_85oFWX= zmJ^dQAS^V@$s-ap|T= z63Yp36-4;}6asuSNBl|$F6TxI_Y(dlrY^C}?$KC&$uLWvFe-?kY%y9y?4V~!9FxMu zZbZ>)P`8xXJ%~`h!>D%pqK<&-{NClv5lj!iTbZQeCU37xjAX8?2DxLxEeLsBU7s-1 zN7w&7uJOQnbPp;lK3<)L$2jqLBA;wDb@4no1ih10RP$!I*91@UHEhtJe!Y5i>eQwy zW&15mvwijk?%;7qxgnx%Zkpqk_6M4}xJR0nyD(I2B=#1&)8d2{7ziCUZq$eafruPX z<(3HCfd_X-dc!k@N<;4IXNrsyJ#b1AvRZ`;jWoE!8G5G zfglAu=_-7aH|#iOXN&BFZQjAdj&esTPz=Ng1p@`+SfOT#yeS3TDI#E4`IxN3N(3or zclMTWM=4MYcA#KJO`3>&(4V6@LAeta_~5C~nAW?*kpd}*7}#5Ihl&U^u6In!-IR|S zgS7=m6R3zZR9=1IjS%RhZB5Ja7I!D6@PKO_M{lTBg*Vf($lhs+VN4^_pga(QibvE+ zD~V~y>46HTwA~%kS|)_Y<%2s7R6IKc7p;akAF?27C>0I0Ffe@n#URlTpKi6%7Cngl zz(|6DV%>>ttIeq~s(9!SoU5}&^marnfzQvHrl!eZ++lZ?hz_9^Ec$NftlqRbsOCc( z0f}i?8W6S0#;;K9K*Ban!Mci*sW=`T+1}A{$QuO*>mdh$OTtqe*ReYX#D(m9$U%v4 zpm?!Mxo)aPFESOt5R6g36B&?!y0uAzJ75~W2!X7f&DW7T@W&R1p*pJs)4TtK$QBVQXs_x{ zqyRFxwKGnsj>g_mgHv@=IwTPqLh-?PWk7zWeyQWW#NIMZEATkBX>`Q(3r>EpZl>}O zBd=S>)JY+F+DXG&X-1-VDsfM|8HwrDgA75UuuA?FH3VtIRw9gsyJ>pOM22dVaw{OR zwkKw!#zF`XXA-~_XHo+ruI`SvF}G- z<-%Aa1rEj40CDL6j63u|%eK|4C|n~_{2ft|;1lPny%FwyCA;m*8hmk1F z5sT6-@K@3f0dhH2bSE$!2jJ?1j%X)VKm&l1?nt66>`@lzX*y5?*c^;hVAaY^hl$Np zfIYCr__#;09Sv!i55uSp%2^1bg5O9^tavO@vzQFzPB9}ny2DHl$}J6ILZnd{BgKgD zQwZvT133d$?}Fgm9WobKoT$Oxf%Wi4%u200NODBzvH}%#$Mr_TR_vrebsU{(FpQFr z#?Lk__NXs_Gf^9WhD>vwa>J?sowj{$aU_Ld$GlZ<;vEY!mUS{m{}*4z zEkP}^AeK*Gc6Zb&ZITv4RA;XN0J+T{^)YLE;>p~c5s$Sj1V|@=z`1f@d=4@KAz0qP z991D%v}NuntW`u+Q=utK4CPGm`!PEqH&dFj+>xn@$%;r}nC_0GunsfW8}2v`I34_E zRwIPwXev<(PF1H|yK$^^Vg^YMurtL^m1$h)4KxkK0fRe%bOJ-raYUdb67>Z5yias0 z*&FXPmRttEU3Ns`=t3l3t7a7#kF^8!FbA745TgB(Yu<^)eNEqDcXp}>#9tM+NFy9L ztJ0YYiS14Ni(%k^B8q4(KI;uY$RY<=u&GoGpBdKh3vJGo;&Esjc!TqPh(~A2s4o)| z9}lp^L7Jc-=c;$ewTM7S6icWcVL$@7g%at_rNf$#SQ4r2#Y=4lVaM0(+QP8-q7x2& z`$rC#C_7_wQAJ?bwAkCcX-uKSklLnpgaehyG)$D_C4fl$9@&yGxecxN^@$EQ=hF zjNjMCilr=I`Mn}sz%t#-Nyev)|1Nu8;ZrGqL zlO=GIyHj@rWnY8Io%L%{<%dAy_bl(xo%>p*D~E~X<(gd6>3b{;w#P$UT<#=*DOiIj z!sWG4uMk%AxVvwX2)1r*7g2DWr z6?g*K^au-wzMGaXNUB|6F<$nPwoxLW@Voh4N#W;F4yNM{E|8KtuB!&(qj7_v44ifE z78Vk}^MSlvE-|}BRqUp>-D4Fc@`Hy7mEWzLE1F>$$6y@4Q>0@DpMQW@2I3O4%;>Os zGGGB?l|pQwGF?Mm{D3=OWMJBr>Vmc|X&rWX3CY4xYk6nLn-717a?3iAKhwd_@xfjN zM)F$~iGDSgFd~(Ws?(Xe?V52sZ}vM)1sIfV!CS@V<|kZltw@^2t(4QLurm|oPaY7;{%IT1e2uDqF66^M}Lgi;lPX!lm7p%u zQ9uVxc}J|?`yE4&Z&`b)Q`z!c7pn+Pz#uCIZYc_=Khhyb`3toTwTW<1JVI~4>NXZ~oBK^8Od3t& z63NTzM+^PJC>8_oyuNRLAQ0-gRhQVsDYJ6dTjev?G=GvceoPAXipE?4{s15QIg9|7T_Jl!DS7Px`= zQ4OZeesMk>3wB3&LKI}5-kE=0f1#2M&ZYj$uCBQ z%Bbzhk~-E=v4#S=3J5&hH5><6rK&2r1>J8S-NG@4G8F8E&_3L`jJUubV!&Sodm@xL zNl@6t@QTG!N|XbHfum(W1#5+f4C;EAe{2l#yNV`_F-%40E}i|(rIZ=%&+inX3@ntC zwP9oin#vDVOp785TgYZe3L=wN0lH9bh|o=hK-g0b#RW~v2tmjvaqA zTSQ5L)DUsOv^aqIpnxaVAwvacM~U-)(iRKz?NM;A04fF#Ut# zF6x-skWfmroEx8fc#_a#G#~RdxB8nMlC-i1O5|b4mZA-VhV#R{eV|T+>6rYih)=IE z)K^IKMcRTGCsHa_`zKt5dWVsYg<@G>gftQTWp;dGrO`Bis!*>A%nZ*>>QB-Hbu_Ig zRU|j4nhE#T3{Xb&J4u)nFD(-U5iF-B5w|71VqOM75JZJDfm1&> z$P{)%3$fIPv5V3k;lAs|lb8fV4Fv|QCsV%}1$XwzSBqu_qnS*I@gj5((kO+^~8bBVg z7?@|1LHxLnvlCW-2r!I^v3e553u73YK@lR5cL;)&YUp-S*%#m|2?fAP0ALh;62!up z9mOMH@36W%2Qyh^gcOVy$%T?bpeX|mFu6!vZ| zIcsf>WlPrPyt9*1l^ft4iz>JS65cr^dqZ{~gF8wk+}^5LgG5#lvetm{c_Xt1?-0m$ z2aM^Rnl-A+of0vQhV@PT2-gjYWgxj{H|0!&{akI3g#!#!on&H)vgUL^xFZWSYiN(K zol;$fFm;Q_gxtyCV2zJZI3fg7$J8n&QS}VHWg6~=nq;wDXM{WHAlj)UT#n+>g^=i- zgCc3LCgL%fM*e$EghYEKGq;@yiK$+mk}HhFC{L3pAaKT0sqHJ0m5!7oCwrWsAAs`|>!$p+#{RrwlPE)@`_9>K&F_ zqCEWLBj^r0!VUa-2X!uDx7Ecq@NND5I(eN5hG2Uv=F0%IW|LV$Bd~W&gT2;qIW*>u z@5N~1jZD9$(HwDnLLQ}ROJRHs<$)J$#AMbqHTl1pl8!PN>rTor1rHRmdK5{j!O>&{ zQrtSN^(J(ycWk-}5)ovr%vxeDvKNju0@Lt-u#LwCWHumTm;j`R^wnh1nG(TV%5kRw zMG3*wF6A8sn_bQ`v`lZ%YlX)%4)Et?jdm}xx-sDOiBRLAvO?D%INF3Re?LEL9uF-w~9s8 z0w@-1s3^s!>ZUq1z0-9jUMt3g&e+>-?xlz|IS8sQwjmA%jIhRPsz=mjid8MOYnfW5 zIuVoMr$+=gX_l&e+@X=tY$BX@09b-diZ%MD(thcM-sAk~wO@Ij$HU-A_^)lb_#*i0 zYcp~EOaCG9RP@Q?cz;N|55BjrhdC}^j#K>gwTH7j@0s85OT6s&5BK)G$6oQgr|>`N zo}R)R@&C0g?DaIhSBC#=m6Y5q*?1*>xN=qem$a^#hdmQct=XhiPN&>1xka8|IWxQW zn8{P8P47It$b_pl$)B?D*1PXp)_GZxNy=z7X5nKi-v4M#=Qa3LBWLohE56$P{jSct zicE6NPE+sxVEe)1lFlXgl$ksIzBS($S428T^wY96yGkO_&e8vT`i~_3{jH!d=}ONX z8TfZB)soAS_;)3ZmzH^?Mn=`jVc+v|tK=T;l+&t7&D5~*rdOGMc3RS8^dCw5`&z-_n3X%H9}@D zAuf-bK=$AbeJvkuFADI^1N|(YisMaO^Hre7@`d;gN#*kUaXiNxNFc9_JEDb^@i}%J z`#FsJu_KBu;{QQ%0Y3A{oG|0O8Pn&@ntegmsHqp7n>Bs*oJ;X_kZc#?+9likK3-PU z@R@R;%rkI=aNy>ST~t^tmZa1`@iVe(}A z@2Ty7tHyteo)m2n#oJ1Gi~r}=|Jv)qP?o3vj2i#wIvTkN|IZu$u$up=I`)67`CqKv bKehf>zt{ER<@I0uV{peTrt&lY6ZiiE8T-c6 literal 0 HcmV?d00001 diff --git a/Resources/nvidia.png b/Resources/nvidia.png new file mode 100644 index 0000000000000000000000000000000000000000..ffaba80e6ff4fd3cf0a5eb898a4ac654ce3c6251 GIT binary patch literal 944 zcmV;h15f;kP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igG* z00197b7^q^000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0009ENklwK7qG}S*(RN4Uy_~Koqe94hcur3{srH+kIc@_>gebw z)oPV;xvX(qm0~HPSga6*5h4OWua}Z#8EKkoyS*#zc3YDq5z}lo5fNIg7R6$bFboMz z3E%YbJc}MW`T=Nx&SvDfX<>2zo`8kk?Rp$nv$j|Mpeo49Osm7-Xm)($7Y5(`$~zq`6Imk+Ic)Gbm-xe@%yiJ-aPjS zQ6a!uiwEGGBW*b*XUn{OSoZEMR zdd$7yb982ppH_ci=qW?9Q{(FUt1RC>%eyap$JU{nOg z4)1*#=r^A_IdLLpXeQ z>-UL^5hm;r9|;(JewW=p2lR)}DiTDh)>@Il!9g{~V0<41HNG#|uE()gn>;qASeIjS z53Hl>gS{W=-Jc60o~X4}Jb-e!%*zW4jE#+RbYcPx_VBh((Yke-`pwfko-DHd{Q%*e z1^)O^n0aOf-}g~f{6e9yG(SJj^z<|rFTO<(gwkp^xpe6xW}kbO@rlFS{pT;1u71qi zi)SdsRW2+p%KG{`+uPgXM^UsC$1&}8n_8{LjTzOR-oaNfP2X#`k^Q+}xCb zfr0%JOQn(;V-BcOKo0VGp7-Be`iKYToT{pb?3ZW&`u+a?s~(|it>ynnRrwcij&ld( S>>qRh0000Px#24YJ`L;!67jR4Pj*I#h}000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igG% z5f>qA7p`0Y00L1-L_t(I%Z-xVOH*+e$G^Yx+fk1@XH%*Lip`hMi_%&P34(}T{sSQ@ zNX#3d2)gc~o38o?3NMRHo!@!7h>6iszwq$f zJfG*C2_dkbhzJ0{ImhhmEE$FYS(cYOJ3EiD{Sxek7eIrBVsWb8{2AyL%V_ICevfv7IEGb4-1Wkh4%kSKmz(G$(i}4XvXMKA(>P^rw(zS+Fb% zLI@Dij(wR9Q|$F9k*pHcH`1$T&uKCgqDpMVI{-kEBMXaSSW3xytM^aW(_@k z*I_$Vj68mXw&NY>_4`@n0z2K3Z6lS-jsN&OK}P>=GQ0hh?jIzo(C^Z) znWp(y<%%Jf&tFLdCy54!$bK?Rc6|ep;v%ZkDEMN8J_G_}7)DiC2mvWm&_6aUErAAZ z0T(X-4oCt&u4|ye#EmFzIVrB=~b|imnf=E z#8d@=lP8ek9A{3Sx>|XxYGOo$Zwm`Q6Juk_;b6#-XTXGEV56l412?YC`2BvL5aPch zFw3&QIY(aC+oz@@i@9tTnyTXbx!#D!bM)+9FaZ1pm04r-q^54v00000NkvXXu0mjf DOfEL} literal 0 HcmV?d00001 diff --git a/Resources/voltage.png b/Resources/voltage.png new file mode 100644 index 0000000000000000000000000000000000000000..3721f55c6610bd9c9e338c8afef78f983d22d25b GIT binary patch literal 639 zcmV-_0)YLAP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igG+ z6&nq2q#f1(000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0005nNkl?xD zA`A=+3@rFGnJY1KXe*0{8R$r*@iM=({{HRL|9xi|JI_4&U;UGT;U7)|EEJe^1AWXA zv{VEWwIp8&viy6`@ba_B$7NeTC9OI2e;u+~xB;H#qHO+-9f3pkh5Y_f(WfZqz`16C6 z;mZ$phSy&i|G)mkaO~@EhH0<=Ff7Ih0~kp3Pzmz)(3;Q3aF_4fYfgrnPxL<=KJ$3h z&Z93UZ@?Ls@Z{w?A7(Gw_GZ=Hw+x?gMKvQd zbqVnBu`Co4WV4eL{. + 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 --git a/Utilities/CrashReport.cs b/Utilities/CrashReport.cs new file mode 100644 index 0000000..8d6af24 --- /dev/null +++ b/Utilities/CrashReport.cs @@ -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 . + 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 --git a/Utilities/EmbeddedResources.cs b/Utilities/EmbeddedResources.cs new file mode 100644 index 0000000..466b502 --- /dev/null +++ b/Utilities/EmbeddedResources.cs @@ -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 . + 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 --git a/Utilities/PInvokeDelegateFactory.cs b/Utilities/PInvokeDelegateFactory.cs new file mode 100644 index 0000000..10caa8e --- /dev/null +++ b/Utilities/PInvokeDelegateFactory.cs @@ -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 . + 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 wrapperTypes = + new Dictionary(); + + 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(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(); + } + } +}