
CONTROLBUILD = 148;
if ( typeof(CODEBASEPATH) == "undefined" )
	CODEBASEPATH = "../pcpitstop";

if ( !document.all || navigator.appVersion.indexOf("Mac") != -1 ) {
	alert("This utility requires IE4+ running Microsoft Windows.");
	document.history.go(-1);
}

Config = {};
Tests = {};
Drives = [];
Disks = [];
Devices = {};
Monitors = [];
Apps = [];
CDs = [];

document.write('<OBJECT ID="sys" CLASSID="CLSID:0E5F0222-96B9-11D3-8997-00104BD12D94" codebase="'+CODEBASEPATH+'/PCPitStop.CAB#Version=1,0,0,'+CONTROLBUILD+'"> </OBJECT>');

function ActivateControls(noctlurl, declineurl)
{
	if ( !document.sys || !sys.ControlBuild || sys.ControlBuild < CONTROLBUILD) {
		if ( noctlurl )
			document.location = noctlurl;
		else
			alert("You don't appear to have the diagnostic utility installed.");
		return false;
		}
	if ( !sys.Enable2(0) ) {
		if ( declineurl )
			document.location = declineurl;
		else
			alert("Unable to run the diagnostic utility, permission declined.");
		return false;
	}
	cpu = sys.cpuObject;
	disk = sys.diskObject;
	memory = sys.memoryObject;
	video = sys.videoObject;
	CDDrive = sys.cddriveObject;
	return true;
}


function RunAllTests()
{
	LoadConfiguration();
	LoadDevices();
	LoadNetwork();
	LoadApps();
	RunCpuLoad();
}

function LoadConfiguration()
{
	LoadConfig();
	LoadDisks();
	LoadDrives();
	LoadTests();
}

function LoadConfig()
{
	if ( Config.nCPUs || (document.Cache && (Config = Thaw(document.Cache.Config.value))) )
		return;
	Config = {};
	var fullbs = navigator.appName + " " + navigator.appVersion;
	var bs = String(fullbs).replace(/^Microsoft Internet Explorer 4.0 \(compatible; /, "");
	if ( bs != fullbs ) {
		bs = bs.replace(/Windows \w+/, "");
		bs = bs.replace(/; DigExt/, "");
		bs = bs.replace(/(;\s)+/g, "; ");
		bs = bs.replace(/(;\s)?\)$/, "");
	}
	Config.Browser = bs;
	Config.serial = String(sys.serial);
	if ( Config.serial.length < 5 || Config.serial == "886288661088" ||
	 	 Config.serial.match(/12345|54321|Serial|DESCDESC|DUMMY|TEST|^(.)\1\1\1\1/) ) {
		Config.serial = "";
	}
	Config.make = sys.make;
	Config.model = sys.model;
	Config.comp_name = sys.comp_name;	// usually in Computer but...
	Config.CPUDesc = String(cpu.CPUDesc).replace(/ with Multimedia Extensions| with MMX| P55C/i,"");
	Config.ClockFrequency = cpu.ClockFrequency;
	Config.ExternalClock = cpu.ExternalClock;
	Config.nCPUs = cpu.nCPUs;
	Config.VideoDesc = video.VideoDesc;
	Config.VidHoriz = video.VidHoriz;
	Config.VidVert = video.VidVert;
	Config.VidBpp = video.VidBpp;
	Config.OSVersion = sys.OSVersion;
	Config.BIOS = sys.BIOS;
	Config.RAMInstalled = memory.RAMInstalled;
	Config.MemorySlots = memory.MemorySlots;
	Config.FreeMemorySlots = memory.FreeMemorySlots;
	Config.MemoryType = memory.MemoryType;
	Config.isLaptop = sys.isLaptop;
	Config.WindowsInstallDate = StdDate(sys.WindowsInstallDate);
	sys.FilePath(2)="";	//windows system directory
	if ( document.Cache )
		document.Cache.Config.value = Freeze(Config);
	Status.Update("");
}

function LoadTests()
{
	if ( Tests.NumFonts || (document.Cache && (Tests = Thaw(document.Cache.Tests.value))) )
		return;
	Tests = {};
	Status.Update("Checking software...");
	Tests.ControlBuild = sys.ControlBuild;
	Tests.Flags = sys.Flags;
	Tests.IEFlags = sys.IEFlags;
	Tests.IEProxyServer = sys.IEProxyServer;
	Tests.IEAutoConfigURL = sys.IEAutoConfigURL;
	sys.FilePath(1)="";	//windows directory
	sys.Filename="wscript.exe";
	var WSHVer=String(sys.FileVersion);
	if (WSHVer.toLowerCase()=="file not found") {	//On Windows 2000, wscript is in the system32 directory
		sys.FilePath(2)="";	//windows system directory
		sys.Filename="wscript.exe";
		WSHVer=String(sys.FileVersion);
	}
	Tests.WSHVer = WSHVer;
	Tests.PagingDrive = sys.PagingDrive;
	Tests.MinPagingFileSize = sys.MinPagingFileSize;
	Tests.MaxPagingFileSize = sys.MaxPagingFileSize;
	Tests.MaxPhysPage = sys.MaxPhysPage;
	Tests.MinFileCache = sys.MinFileCache;
	Tests.MaxFileCache = sys.MaxFileCache;

	Status.Update("Checking memory...");
	Tests.RAM = memory.RAM;
	Tests.FreeResources = Math.min(sys.FreeSystemResources(0),Math.min(sys.FreeSystemResources(1),sys.FreeSystemResources(2)));
	if ( document.Cache )
		document.Cache.Tests.value = Freeze(Tests);
	Status.Update("");
}

function LoadDisks()
{
	if ( Disks.length || (document.Cache && (Disks = Thaw(document.Cache.Disks.value))) )
		return;
	Disks = [];
	Status.Update("Checking disks...");
	for ( var i = 0; disk.DiskInfo(i); i++ ) {
		var di = Disks[i] = {};
		for ( var j = 0; disk.DiskDetail(j); j++ ) {
			eval("di."+disk.DiskDetailName+"=disk.DiskDetailValue");
		}
	}
	if ( document.Cache )
		document.Cache.Disks.value = Freeze(Disks);
	Status.Update("");
}

var DiskHealthResults = [
	"OK", "Unknown(1)",	"Not tested", "Unknown(3)", 
	"Unable to read boot sector", "Error reading FAT copy 1",
	"Error reading FAT copy 2", "FAT1-FAT2 mismatch",
	"Invalid FAT", "Crosslinked files"
];

function LoadDrives()
{
	if ( Drives.length || (document.Cache && (Drives = Thaw(document.Cache.Drives.value))) )
		return;
	Drives = [];
	Status.Update("Checking drives...");
	var C = "C".charCodeAt(0); // start with hard disk, skip floppies
	var j = 0;
	for ( var i = 0; i < 24; i++ ) {
		var Drive=String.fromCharCode(C+i)+":\\";
		disk.DrivePath=Drive;
		if ( disk.DriveType != "No root directory" ) {
			Status.Update("Checking drives..."+Drive);
			var dj = Drives[j] = {};
			dj.DrivePath = disk.DrivePath;
			dj.VolName = disk.VolName;
			dj.VolSer = disk.VolSer;
			dj.DriveType = disk.DriveType;
			dj.PartType = disk.PartType;
			dj.Size = disk.Size;
			dj.cluster_size = disk.cluster_size;
			if ( dj.DriveType == "Hard disk" || 
					(Drive == "C:\\" && dj.DriveType == "Removable") ) {
				DiskHealth.Volume = Drive;
				var sr = DiskHealth.ScanRating;
				dj.ScanRating = (sr==100)? 1 : sr;
				dj.FragmentationPercent = DiskHealth.FragmentationPercent;
				dj.FileFragmentationPercent = DiskHealth.FileFragmentationPercent;
				dj.Free = disk.Free;
				dj.LastScan = StdDate(disk.LastScan);
				dj.LastOpt = StdDate(disk.LastOpt);
	
			}
			j++;
		}
	}
	if ( document.Cache )
		document.Cache.Drives.value = Freeze(Drives);
	Status.Update("");
}

function RunCpuLoad()
{
	Status.Update("Checking CPU load...");
	Tests.CpuLoad = cpu.CpuLoad;
}

function LoadNetwork()
{
	LoadDevices();
	if ( Tests.PingSite )
		return;
	Tests.PingSite = PingSite;
	Status.Update("Pinging "+Tests.PingSite+"...");
	var npings=5, ngood=0, PingRTT=0;
	for ( var i=0; i<npings; i++ ) {
		sys.Sleep(100);
		var ping = sys.Ping(Tests.PingSite);
		if ( ping >= 0 ) {
			ngood++;
			PingRTT += ping;
		}
	}
	Tests.PingRTT = ngood? Round(PingRTT/ngood, 0) : -1
	Tests.PingPctLoss = Round(100*(npings-ngood)/npings,2);
	Tests.RWin = sys.RWin;
	Tests.IPAddress = sys.IPAddress;
//	Tests.UpBandwidth = sys.UpBandwidth;
//	Tests.DnBandwidth = sys.DnBandwidth;
	if ( document.Cache )
		document.Cache.Tests.value = Freeze(Tests);
	Status.Update("");
}

function LoadDevices()
{
	LoadMonitors();
	if ( Devices["system"] || (document.Cache && (Devices = Thaw(document.Cache.Devices.value))) )
		return;
	Devices = {};
	Status.Update("Checking devices...");
	for ( var i=0; sys.DeviceInfo(i); i++) {
		var dclass = String(sys.DeviceClass).toLowerCase();
		if ( !Devices[dclass] )
			Devices[dclass] = [];
		var vendor = sys.DeviceVendor || "";
		vendor = vendor.replace(/^\(Standard[^\)]*\)|Generic\s*/i, "");
		vendor = Unclutter(vendor)
		var product = Unclutter(sys.DeviceProduct || "");
		Devices[dclass][Devices[dclass].length] = {
			Class: dclass, Vendor: vendor, Product: product, 
			DriverDate: StdDate(sys.DeviceDriverDate),
			Problem: sys.DeviceProblem, Status: sys.DeviceStatus
		};
	}
	if ( document.Cache )
		document.Cache.Devices.value = Freeze(Devices);
	Status.Update("");
}

function LoadMonitors()
{
	if ( Monitors.length || (document.Cache && (Monitors = Thaw(document.Cache.Monitors.value))) )
		return;
	Monitors = [];
	for ( var i=0; i < sys.NMonitors; i++ ) {
		Monitors[Monitors.length] = {
			Monitor: sys.Monitor(i), 
			MonMaxHRes: sys.MonMaxHRes(i), MonMaxHSize: sys.MonMaxHSize(i),
			MonMaxVRes: sys.MonMaxVRes(i), MonMaxVSize: sys.MonMaxVSize(i),
			ManufactureYear: sys.ManufactureYear(i),
			ManufactureWeek: sys.ManufactureWeek(i),
			MonSerialNr: sys.MonSerialNr(i)
		};
	}
	if ( document.Cache )
		document.Cache.Monitors.value = Freeze(Monitors);
}

function LoadApps()
{
	if ( Apps.length )	// already loaded
		return;
	Status.Update("Checking software...");
	for ( var i=0; sys.enumApps(i); i++ ) {
		var ai = {};
		//	"FileName" "Running" "FileSize"	"LastChanged" "Vendor"
		//	"Version" "Product"	"InternalName" "FileDescription" "RunFrom"
		for ( var j = 0; sys.enumAppDetails(j); j++ ) {
			ai[sys.AppDetailName] = sys.AppDetailValue;
		}
		if( i%10 == 0 )
			Status.Update("Checking software..."+i);
		var vendor = Unclutter(ai.Vendor || "");
		var product = Unclutter(ai.Product || "");
		var version = ai.Version || "";
		product = product.replace(/ Operating System| for Windows.*/,"");
		if ( !vendor && !product )
			product = ai.FileDescription || "";
		else if ( product.substr(0,vendor.length) != vendor )
			product = vendor + " " + product;
		Apps[Apps.length] = {
			Product: product, Version: version, Running: ai.Running, 
			FileName: ai.FileName, RunFrom: ai.RunFrom
		};
	}
	Apps.sort(function(a,b){return a.Product<b.Product?-1:a.Product>b.Product?1:0});
	Status.Update("");
}

function RunCPUMemTests()
{
	Status.Update("Testing CPU MHz...");
	Config.ClockFrequency = cpu.ClockFrequency;
	Tests.TestClockFrequency = cpu.TestClockFrequency;
	Status.Update("Checking CPU Load...");
	Tests.CpuLoad = cpu.CpuLoad;
	Status.Update("Testing CPU integer performance...");
	Tests.IntSpeed = Round(cpu.IntSpeed,0);
	Status.Update("Testing memory performance...");
	Tests.RAM = memory.RAM;
	Tests.MemSpeed = Round(memory.MemSpeed,0);
	Status.Update("");
}

function RunDriveTests()
{
	Status.Update("Testing drives...");
	for ( var i = 0; i < Drives.length; i++ ) {
		var d = Drives[i];
		if ( d.DriveType == "Hard disk" || 
				(d.DrivePath == "C:\\" && d.DriveType == "Removable") ) {
			Status.Details(d.DrivePath);
			disk.DrivePath=d.DrivePath;
			d.Size = disk.Size;
			d.Free = disk.Free;
			d.RecycleCurrent = disk.RecycleCurrent;
			d.RecycleMaxPct = disk.RecycleMaxPct;
			DiskHealth.Volume = d.DrivePath;
			var ScanRating = DiskHealth.ScanRating;
			if ( ScanRating < 3 || ScanRating == 100 ) { // safe to test
				Status.Details(d.DrivePath+" (cached)");
				disk.CachedSpeed;	// tickle the cache and throw this away
				sys.Sleep(5000);
				d.CachedSpeed = Round(disk.CachedSpeed,2);
				Status.Details(d.DrivePath+" (uncached)");
				sys.Sleep(5000);
				d.UncachedSpeed = Round(disk.UncachedSpeed,2);
			}
		}
	}
	Status.Update("Calculating temp/cache usage...");
	disk.DrivePath="C:\\";
	Tests.TempFileUsage = disk.TempFileUsage;
	Tests.TempPath = disk.TempPath;
	Tests.ieCacheCurrent = disk.ieCacheCurrent;
	Tests.ieCachePath = disk.ieCachePath;
	Tests.nsCacheCurrent = disk.nsCacheCurrent;
	Tests.nsCachePath = disk.nsCachePath;
	Status.Update("");
}

function RunVideoTests()
{
	Status.Update("Testing video...");
	Config.VidHoriz = video.VidHoriz;
	Config.VidVert  = video.VidVert;
	Config.VidBpp   = video.VidBpp;
	Tests.VidSpeed = Round(video.VidSpeed,2)
	Status.Update("");
}

function RunCDTests()
{
	Status.Update("Detecting CD-ROM/R/RW drives...");
	CDs = [];
	for ( var i=0; CDDrive.enumCD(i); i++ ) {
			var Type = "CD-ROM";
			var TypeCode = CDDrive.CDType;
			var rs = CDDrive.MaxReadSpeed;
			var ws = CDDrive.MaxWriteSpeed;
			if ( TypeCode & 0x2000 )
				Type = "DVD-RAM";
			else if ( TypeCode & 0x1000 )
				Type = "DVD-RW";
			else if ( TypeCode & 0x0200 )
				Type = "CD-RW";
			else if ( TypeCode & 0x0100 )
				Type = "CD-R";
			else if ( TypeCode & 0x0018 )
				Type = "DVD-ROM";
			if ( rs )
				rs = Math.round(rs/176)+"X read";
			else
				rs = "";
			if ( ws )
				ws = Math.round(ws/176)+"X write";
			else
				ws = "";
		CDs[CDs.length] = {CDModel: CDDrive.CDModel,
			Type: Type, ReadSpeed: rs, WriteSpeed: ws};
	}
	Status.Update("");
}


function OSFormalName(OS)
{
	OS = (OS || "").replace(/\s+$/,"");
	if ( OS == "Windows Me 4.90.3000" )
		return "Windows Me";
	if ( OS == "Windows 98 4.10.2222  A" )
		return "Windows 98 SE";
	if ( OS == "Windows 98 4.10.1998" )
		return "Windows 98";
	if ( OS == "Windows 95 4.0.1111  B" )
		return "Windows 95 OSR2";
	if ( OS == "Windows 95 4.0.1212  B" )
		return "Windows 95 OSR2.1";
	if ( OS == "Windows 95 4.0.950" )
		return "Windows 95";
	OS = OS.replace(/^Windows NT 4.0.1381/, "Windows NT");
	OS = OS.replace(/^Windows 2000 5.0.2195/, "Windows 2000");
	OS = OS.replace(/Service Pack /,"SP");
	return OS;
}

function VidBppToColors(bpp)
{
	switch ( bpp ) {
	 case 4:  return "16";
	 case 8:  return "256";
	 case 15: return "32,768";
	 case 16: return "65,536";
	 case 24: 
	 case 32: return "16 million";
	 default: return bpp+" bits per pixel";
	}
}

function Unclutter(name)
{
	name = name.replace(/[\x00-\x1F]+/g, " ");
	name = name.replace(/ [Ii]ncorporated| [Cc]orp(oration)?\.?|,.*$| [Cc]ompany| Ltd\.?/,"");
	name = name.replace(/\([Rr]\)|\([TtSs][Mm]\)|\xAE/g,""); // 0xAE is copyright symbol
	name = name.replace(/\s+$/,"");
	return name;
}

function StdDate(dts, withTime)
{
	var dt = new Date(dts);
	if ( !dt.getTime() || dt.getTime() < 1 || dt.getFullYear > 2100 )
		return "";
	var str = (dt.getMonth()+1)+"/"+dt.getDate()+"/"+dt.getFullYear();
	if ( !withTime )
		return str;
	var hh = String(dt.getHours());	
	if ( hh.length == 1 ) hh = "0" + hh;
	var mm = String(dt.getMinutes());	
	if ( mm.length == 1 ) mm = "0" + mm;
	var ss = String(dt.getSeconds());	
	if ( ss.length == 1 ) ss = "0" + ss;
	return str + " " + hh+":"+mm+":"+ss;
}

function Round(n, d)
{
	var p = Math.pow(10, d||0);
	return Math.round(n*p)/p;
}

function Freeze(item)
{
	var it = typeof(item);
	if ( it=="undefined" )
		return "undefined";
	if ( item==null )
		return "null";
	var ic = (it!="object")? null : item.constructor;
	if ( it=="function" || it=="boolean" || it=="number" || ic==Boolean || ic==Number )
	    return item.toString();
	if ( it=="string" || ic==String ) {
		item = item.replace(/(["\\])/g,'$1$1');
		item = item.replace(/\x0D/g,"\\r");
		item = item.replace(/\x0A/g,"\\n");
		return '"'+item+'"';
	}
	if ( it!="object" )
		return "??";
	var str = "";
	if ( ic===Array ) {
		for ( var i=0; i < item.length; i++ )
			str += Freeze(item[i])+",";
		return "["+str.substr(0,str.length-1)+"]";
	}
	if ( ic==Object ) {
		for ( var i in item )
			str += '"'+i+'":'+Freeze(item[i])+",";
		return "{"+str.substr(0,str.length-1)+"}";
	}
	if ( ic==Date )
		return 'new Date('+item.getTime()+')';
	if ( ic==RegExp )
		return "/"+item.source+"/"+(item.global?"g":"")+(item.ignoreCase?"i":"");
	if ( item.toSource )
		return item.toSource();
	return '"??"';  // unhandled 
}

function Thaw(block)
{
	var NaN = Number.NaN;
	var Infinity = Number.POSITIVE_INFINITY;
	var _RET, undefined;
	if ( block == "" || block == null )
		return undefined;
	eval("_RET="+block);
	return _RET;
}

