2016-01-01

Books read 2015

Below are the books that I read during 2015 and my rating out of 5.
RatingTitleAuthor
5Origins of a D-List SupervillainJim Bernheimer
5AnathemNeal Stephenson
5Seveneves: A NovelNeal Stephenson
5Year Zero: A NovelRob Reid
5The Wasp FactoryIain Banks
5The First Fifteen Lives of Harry AugustClaire North
5Flowers For AlgernonDaniel Keys
5Steel World: Undying Mercenaries, Book 1B. V. Larson
5Dust World: Undying Mercenaries, Book 2B. V. Larson
5Tech World: Undying Mercenaries, Book 3B.V. Larson
4Emperor Mollusk Versus the Sinister BrainA. Lee Martinez
4Battle Station: Star Force, Book 5B. V. Larson
4Conquest: Star Force, Book 4B. V. Larson
4Empire: Star Force, Book 6B. V. Larson
4Extinction: Star Force, Book 2B. V. Larson
4Machine World: Undying Mercenaries, Book 4B. V. Larson
4Rebellion: Star Force, Book 3B. V. Larson
4The Chaplain's WarBrad R. Torgersen
4The Cycle of Arawn: The Complete TrilogyEdward W. Robertson
4ArmadaErnest Cline
4TransitionIain Banks
4Secrets of a D-List SupervillainJim Bernheimer
4Blood Rites: The Dresden Files, Book 6Jim Butcher
4Changes: The Dresden Files, Book 12Jim Butcher
4Cold Days: Dresden Files, Book 14Jim Butcher
4Dead Beat: The Dresden Files, Book 7Jim Butcher
4Death Masks: The Dresden Files, Book 5Jim Butcher
4Fool Moon: The Dresden Files, Book 2Jim Butcher
4Ghost Story: A Novel of the Dresden FilesJim Butcher
4Grave Peril: The Dresden Files, Book 3Jim Butcher
4Proven Guilty: The Dresden Files, Book 8Jim Butcher
4Skin Game: The Dresden FilesJim Butcher
4Small Favor: The Dresden Files, Book 10Jim Butcher
4Summer Knight: The Dresden Files, Book 4Jim Butcher
4Turn Coat: The Dresden Files, Book 11Jim Butcher
4White Night: The Dresden Files, Book 9Jim Butcher
4The Girl with All the GiftsM. R. Carey
4Nifft the Lean: Nifft, Book 1Michael Shea
4NeverwhereNeil Gaiman
4Ex-CommunicationPeter Clines
4Ex-HeroesPeter Clines
4Ex-PatriotsPeter Clines
4Ex-PurgatoryPeter Clines
4The FoldPeter Clines
4BlindsightPeter Watts
4Altered CarbonRichard K. Morgan
4Starship TroopersRobert A. Heinlein
4SpinRobert Charles Wilson
4Infected: A NovelScott Sigler
4The Pilo Family CircusWill Elliott
3Galactic NorthAlastair Reynolds
3Annihilation: Star Force, Book 7B. V. Larson
3The Dead Sun: Star Force, Book 9B. V. Larson
3Storm Assault: Star Force, Book 8B.V. Larson
3ElantrisBrandon Sanderson
3Dark Eden: A NovelChris Beckett
3The Bad PlaceDean Koontz
3The BridgeIain Banks
3Project 731Jeremy Robinson
3Cinder: Book One of the Lunar ChroniclesMarissa Meyer
3Starship: RebelMike Resnick
3UbikPhilip K. Dick
3Off to Be the WizardScott Meyer
2The Thought PushersDima Zales, Anna Zaires
2The Thought ReadersDima Zales, Anna Zaires

2015-04-07

Command line calendar for Windows

I created a command line calendar utility that others may find useful. Download the zip file from here. I originally coded this as an exercise in Turbo Pascal, translated into Delphi, then recently recoded into PureBasic which can create tightly compiled stand alone console executables - about one quarter the size of Delphi executables.

You can use the utility to create a MSWord doc using a mono font like Courier, by redirecting the output to a file:
cal > cal.txt
You can even fit three full years on one A4 page if you change MSWord's page orientation to landscape and reduce the margins
cal n=36 w=6 > cal.txt

Usage: cal Y=nnnn M=nn N=nn W=[1,2,3,4,6,12] S=nn T
Y = year of calendar; default=current year; cal Y=2000
YX = year of calendar without correction for 0-99
M = start month; default=1 (January)
N = number of months; default=12
W = nr months in a row; default=3
S = nr horizontal spaces between months; default=3
T = use tab instead of spaces - good for export to spreadsheet; cal T > caltab.txt


January 2015           February 2015          March 2015        
Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
             1  2  3    1  2  3  4  5  6  7    1  2  3  4  5  6  7
 4  5  6  7  8  9 10    8  9 10 11 12 13 14    8  9 10 11 12 13 14
11 12 13 14 15 16 17   15 16 17 18 19 20 21   15 16 17 18 19 20 21
18 19 20 21 22 23 24   22 23 24 25 26 27 28   22 23 24 25 26 27 28
25 26 27 28 29 30 31                          29 30 31          
                                                                
April 2015             May 2015               June 2015         
Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
          1  2  3  4                   1  2       1  2  3  4  5  6
 5  6  7  8  9 10 11    3  4  5  6  7  8  9    7  8  9 10 11 12 13
12 13 14 15 16 17 18   10 11 12 13 14 15 16   14 15 16 17 18 19 20
19 20 21 22 23 24 25   17 18 19 20 21 22 23   21 22 23 24 25 26 27
26 27 28 29 30         24 25 26 27 28 29 30   28 29 30          
                       31                                       
July 2015              August 2015            September 2015    
Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
          1  2  3  4                      1          1  2  3  4  5
 5  6  7  8  9 10 11    2  3  4  5  6  7  8    6  7  8  9 10 11 12
12 13 14 15 16 17 18    9 10 11 12 13 14 15   13 14 15 16 17 18 19
19 20 21 22 23 24 25   16 17 18 19 20 21 22   20 21 22 23 24 25 26
26 27 28 29 30 31      23 24 25 26 27 28 29   27 28 29 30       
                       30 31                                    
October 2015           November 2015          December 2015     
Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
             1  2  3    1  2  3  4  5  6  7          1  2  3  4  5
 4  5  6  7  8  9 10    8  9 10 11 12 13 14    6  7  8  9 10 11 12
11 12 13 14 15 16 17   15 16 17 18 19 20 21   13 14 15 16 17 18 19
18 19 20 21 22 23 24   22 23 24 25 26 27 28   20 21 22 23 24 25 26
25 26 27 28 29 30 31   29 30                  27 28 29 30 31      


2014-12-28

Books read 2014

Below are the books that I read during 2014 and my rating out of 5.
RatingTitleAuthor
5+The MartianAndy Weir
5+Ready Player OneErnest Cline
5+Gone Girl: A NovelGillian Flynn
5InfluxDaniel Suarez
5GatewayFrederik Pohl
5The World at the End of TimeFrederik Pohl
5At the Mountains of MadnessH. P. Lovecraft
5Against a Dark BackgroundIain M. Banks
5Feersum EndjinnIain M. Banks
5Look to Windward: Culture SeriesIain M. Banks
5MatterIain M. Banks
5Fuzzy NationJohn Scalzi
5Lock InJohn Scalzi
5Old Man's War (OMW#1)John Scalzi
5The Ghost Brigades (OMW#2)John Scalzi
5The Human Division (OMW#5)John Scalzi
5The Last Colony (OMW#3)John Scalzi
5Ghost in the Wires: My Adventures as the World’s Most Wanted HackerKevin Mitnick, W.L.Simon
5Red RisingPierce Brown
5Dimension of MiraclesRobert Sheckley
4BlackoutConnie Willis
4Down and Out in the Magic KingdomCory Doctorow
4Freedom (TM)Daniel Suarez
4The Pixar Touch: The Making of a CompanyDavid A. Price
4The Dragon in the SeaFrank Herbert
4Beyond the Blue Event HorizonFrederik Pohl
4Heechee RendezvousFrederik Pohl
4The Annals of the HeecheeFrederik Pohl
4The Boy Who Would Live ForeverFrederik Pohl
4The Space MerchantsFrederik Pohl, C.M.Kornbluth
4The AlgebraistIain M. Banks
4Confessions of a D-List SupervillainJim Bernheimer
4Storm FrontJim Butcher
4A Hymn Before Battle: Legacy of the AldenataJohn Ringo
4Rules of PreyJohn Sanford
4Agent to the StarsJohn Scalzi
4The Android's DreamJohn Scalzi
4Zoe's Tale (OMW#4)John Scalzi
4Monster Hunter InternationalLarry Correia
4Hollow WorldMichael J. Sullivan
4American GodsNeil Gaiman
4The Junkie QuatrainPeter Clines
4TimeboundRysa Walker
4A short stay in HellSteven Peck
4The 9th GirlTami Hoag
3The Stars My DestinationAlfred Bester
3FarsideBen Bova
3Grave SightCharlaine Harris
3All ClearConnie Willis
3The PlaygroundRay Bradbury
3A Canticle for LeibowitzWalter M. Miller
2Kill DecisionDaniel Suarez
2OutlanderDiana Gabaldon
2Whipping StarFrank Herbert
2BrillianceMarcus Sakey
2Zero Day: A Jeff Aiken NovelMark Russinovich
2The Cat Who Walks through WallsRobert Heinlein
2FlashforwardRobert J. Sawyer
2NeuromancerWilliam Gibson

2014-01-01

Books read 2013

Below are the books that I read during 2013 and my rating out of 5. Nearly all books were sourced via audible.com

RatingTitleAuthor
514Peter Clines
5Absolution GapAlastair Reynolds
5Blue Remembered EarthAlastair Reynolds
5Brave New WorldAldous Huxley
5Chasm CityAlastair Reynolds
5Ender's Game Alive: The Full Cast AudioplayOrson Scott Card
5Great North Road - Part OnePeter F. Hamilton
5Great North Road - Part TwoPeter F. Hamilton
5House of SunsAlastair Reynolds
5InversionsIain M. Banks
5Mindstar Rising: The Greg Mandel Trilogy, Book 1Peter F. Hamilton
5Pushing IceAlastair Reynolds
5RedshirtsJohn Scalzi
5Surface DetailIain M. Banks
5The Player of Games: Culture Series, Book 2Iain M. Banks
5The PrefectAlastair Reynolds
4A Quantum Murder: The Greg Mandel Trilogy, Book 2Peter F. Hamilton
4Century RainAlastair Reynolds
4Consider Phlebas: Culture Series, Book 1Iain M. Banks
4ExcessionIain M. Banks
4Heir of Novron: Riyria Revelations, Volume 3Michael J. Sullivan
4Redemption ArkAlastair Reynolds
4Revelation SpaceAlastair Reynolds
4Rise of Empire: Riyria Revelations, Volume 2Michael J. Sullivan
4The Hydrogen Sonata: Culture, Book 10Iain M. Banks
4The Nano Flower: The Greg Mandel Trilogy, Book 3Peter F. Hamilton
4Theft of Swords: Riyria Revelations, Volume 1Michael J. Sullivan
4Time for the StarsRobert A. Heinlein
4Use of Weapons: Culture Series, Book 3Iain M. Banks
3On the Steel BreezeAlastair Reynolds
3The Man in the High CastlePhilip K. Dick
2Terminal WorldAlastair Reynolds

2013-09-04

Locate the local path for Google Drive, DropBox, SkyDrive in VBscript

When scripting up a storm, I sometimes need to place output into folders that I know will be stored in the cloud. The following script set will return the folder on the local windows drives where the cloud apps will be syncing their files, or an empty string if the script fails due to the cloud application having not been installed or some other issue such as Microsoft moving their registry setting or Google changing the readability of their config file.
WScript.Echo "Dropbox : " & GetDropBoxFolder
WScript.Echo "Google Drive : " & GetGoogleDriveFolder
WScript.Echo "Skydrive : " & GetSkyDriveFolder

Function GetSkyDriveFolder ()
Dim WshShell, f
set WshShell = WScript.CreateObject ("WScript.Shell")
On Error Resume Next
f = WshShell.RegRead("HKEY_CURRENT_USER\Software\Microsoft\SkyDrive\UserFolder") ' Windows 7
If Err.Number <> 0 Then
 Err.Clear
 ' Allegedly this is windows 8 key, however this appears not to be the Case
 f = WshShell.RegRead("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\SkyDrive\UserFolder")
End If
GetSkyDriveFolder = f & ""
On Error GoTo 0
End Function

Function GetAppDataFolder ()
' returns C:\\\AppData\Roaming
' returns empty strong if not found
Dim WshShell, f
set WshShell = WScript.CreateObject ("WScript.Shell")
On Error Resume Next
f = WshShell.ExpandEnvironmentStrings("%APPDATA%") & ""
If Err.Number Then Err.Clear
On Error GoTo 0
GetAppDataFolder = f
End Function

Function GetLocalAppDataFolder ()
' returns C:\\\AppData\Roaming
' returns empty strong if not found
Dim WshShell, f
set WshShell = WScript.CreateObject ("WScript.Shell")
On Error Resume Next
f = WshShell.ExpandEnvironmentStrings("%LOCALAPPDATA%") & ""
If Err.Number Then Err.Clear
On Error GoTo 0
GetLocalAppDataFolder = f
End Function

Function Base64Decode(ByVal base64String)
'rfc1521 1999 Antonin Foller, Motobit Software, http://Motobit.cz
Const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
Dim dataLength, sOut, groupBegin
base64String = Replace(base64String, vbCrLf, "")
base64String = Replace(base64String, vbTab, "")
base64String = Replace(base64String, " ", "")
dataLength = Len(base64String)
If dataLength Mod 4 <> 0 Then
  Err.Raise 1, "Base64Decode", "Bad Base64 string."
  Exit Function
End If
Dim numDataBytes, CharCounter, thisChar, thisData, nGroup, pOut
For groupBegin = 1 To dataLength Step 4
  numDataBytes = 3
  nGroup = 0
  For CharCounter = 0 To 3
    thisChar = Mid(base64String, groupBegin + CharCounter, 1)
    If thisChar = "=" Then
      numDataBytes = numDataBytes - 1
      thisData = 0
    Else
      thisData = InStr(1, Base64, thisChar, vbBinaryCompare) - 1
    End If
    If thisData = -1 Then
      Err.Raise 2, "Base64Decode", "Bad character In Base64 string."
      Exit Function
    End If
    nGroup = 64 * nGroup + thisData
  Next
  nGroup = Hex(nGroup)
  nGroup = String(6 - Len(nGroup), "0") & nGroup
  pOut = Chr(CByte("&H" & Mid(nGroup, 1, 2))) +  Chr(CByte("&H" & Mid(nGroup, 3, 2))) +  Chr(CByte("&H" & Mid(nGroup, 5, 2)))
  sOut = sOut & Left(pOut, numDataBytes)
Next
Base64Decode = sOut
End Function

Function GetDropBoxFolder ()
' Returns Empty String If host.db not found and decoded properly
' %APPDATA%\Dropbox\host.db
Dim fso, hostdb, p, f
f = ""
p = GetAppDataFolder
If p <> "" Then
 On Error Resume Next
 Set fso = CreateObject("Scripting.FileSystemObject")
 Set hostdb = fso.OpenTextFile(p & "\Dropbox\host.db", 1, False, -2)
 If Err.Number <> 0 Then
  Err.Clear
 Else
  f = hostdb.ReadLine & "" ' junk line
  If Err.Number <> 0 Then Err.Clear
  f = hostdb.ReadLine & "" ' this line!
  If Err.Number <> 0 Then Err.Clear
  hostdb.Close
  If Err.Number <> 0 Then Err.Clear
  If f <> "" Then f = Base64Decode(f) & ""
  If Err.Number <> 0 Then Err.Clear
 End If
 On Error GoTo 0
End If
GetDropBoxFolder = f
End Function

Function GetGoogleDriveFolder ()
' Returns Empty String If sync_config.db not found and decoded properly
' %LOCALAPPDATA%\Google\Drive\sync_config.db
' local_sync_root_pathvalue\\?\C:\Users\thsforsy\Google Drive[RS][ETX][EOT]
' 123456789012345678901234567890
Dim fso, datafile, p, alltext, cleantext, f, i
f = ""
p = GetLocalAppDataFolder
If p <> "" Then
 On Error Resume Next
 Set fso = CreateObject("Scripting.FileSystemObject")
 Set datafile = fso.OpenTextFile(p & "\Google\Drive\sync_config.db", 1, False, 0)
 If Err.Number <> 0 Then
  ' No folder, just let the system exit and return empty string
  Err.Clear
 Else
  startpos = 0
  Do While Not datafile.AtEndOfStream And startpos = 0
   alltext = datafile.ReadLine & ""
   If Err.Number <> 0 Then Err.Clear
   cleantext = ""
   For i = 1 To Len(alltext)
    If Asc(Mid(alltext,i,1)) = 30 OR Asc(Mid(alltext,i,1)) >=32 Then cleantext = cleantext & Mid(alltext,i,1)
   Next
   startpos = InStr(1,cleantext,"local_sync_root_pathvalue")
   If startpos > 0 Then
    endpos = startpos + 29
    Do While endpos < Len(cleantext) And Asc(Mid(cleantext,endpos,1)) >= 32
     IF Asc(Mid(cleantext,endpos,1)) <> 0 Then f = f & Mid(cleantext,endpos,1)
     endpos = endpos + 1
    Loop
   End If
  Loop
  datafile.Close
  If Err.Number <> 0 Then Err.Clear
 End If
 On Error GoTo 0
End If
GetGoogleDriveFolder = Trim(f)
End Function

2012-07-12

Normal distribution from uniform random in VBscript

Because everyone needs to generate a normally distributed random number set at least once in their life, right? Why not do it in the programming language that comes with nearly every version windows since Microsoft started ripping off Apple.
' * Static *
Dim NormalRandToggle, NormalRandTemp

Function NormalRand(ByVal thisMean, ByVal thisStandardDev)
' Outputs Gaussian/Normal distributed random numbers using Box-Muller algorithm.
' Note the function creates two at a time,
' so global variables are used to store and output the second number on demand
If NormalRandToggle = 1 Then
 NormalRandToggle = 0
 NormalRand = NormalRandTemp
Else
 NormalRandToggle = 1
 Dim R1, R2, rad, t
 Do Until rad > 0.0 AND rad < 1.0
  R1 = (2.0 * Rnd()) - 1.0
  R2 = (2.0 * Rnd()) - 1.0
  rad = R1^ 2 + R2^2
 Loop
 t = Sqr(-2.0 * Log(rad) / rad)
 NormalRandTemp = t * R2 * thisStandardDev + thisMean
 NormalRand = t * R1 * thisStandardDev + thisMean
End If
End Function



' *** TEST ***

Randomize
Dim i, R, N, S, SS, M, V, SD
N = 0
S = 0
SS = 0
For i = 1 To 1000000
 N = N + 1
 R = NormalRand (100, 33)
 S = S + R
 SS = SS + R^2
Next
M = S / N
V = SS / N - M ^ 2
SD = Sqr(V)
WScript.Echo "Mean = " & M & " Var = " & V & " StdDev = " & SD
Thanks to Zaza for example VB code and Peter Kankowski for the one pass variance/standard deviation calculation in the test.

2012-01-20

Windows 64bit scripting host forced into 32bit

Error: [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified
Code: 80004005

Using Windows Script Host (WSH, CScript, VBS) to access Microsoft Access database files will bring this error up in 64 bit Windows. You need to force your script to run in 32 bit mode. The following code attached to the top of your script should detect if you are in a 64 bit Windows OS and will attempt to run the 32 bit cscript.
(Update 2014-02-28: Aborts when there are spaces in the path, added quotes to fix this) (Update 2016-01-28: fix for 64bit office vs 32bit office)

' ***************
' *** 64bit check
' ***************
' check to see if we are on 64bit Windows OS with 32bit MS Office -> re-run this script forcing 32bit mode cscript

Dim r32OSbit, r32Officebit
r32OSbit = CPUbitness()
r32Officebit = OfficeBitness()
WScript.Echo "OS mode " & r32OSbit & " with Office " & r32Officebit
If r32OSbit = "AMD64" AND r32Officebit= "x86" Then
 If MatchAnyArg("restart32") = 0 Then RestartWithCScript32 "restart32" Else MsgBox "Cannot find 32bit version of cscript.exe or unknown OS type " & r32OSbit
 WScript.Quit
End If

' Function to determine bitness of the installed Microsoft Office
FUNCTION OfficeBitness ()
' Returns x64 or x86, or "?" if no office found
CONST MaxOfficeVer = 20 ' currently 15 (2015-08-04)
CONST MinOfficeVer = 10
DIM objShell, i, Found, thisNode, regNode
Set objShell = WScript.CreateObject("WScript.Shell")
On Error Resume Next
i = MaxOfficeVer + 1
Found = False
DO
 i = i - 1
 thisNode = "HKLM\Software\Microsoft\Office\" & i & ".0\Outlook\Bitness"
 regNode = objShell.RegRead (thisNode)
 IF Err.Number <> 0 THEN
  Err.Clear
 Else
  Found = True
 End If
LOOP UNTIL i = MinOfficeVer OR Found
IF Found THEN
 OfficeBitness = regnode
 'WScript.Echo regnode & " for office version " & i & ".0"
ELSE
 OfficeBitness = "?"  'No office found in registry range
END IF
END FUNCTION

FUNCTION CPUbitness()
' AMD64 IA64 x86
Dim r32wShell, r32env1
Set r32wShell = WScript.CreateObject("WScript.Shell")
r32env1 = r32wShell.ExpandEnvironmentStrings("%PROCESSOR_ARCHITECTURE%")
CPUbitness = r32env1
Set r32wShell = Nothing
End Function

Function MatchAnyArg(thisArg)
Dim FoundArg, r32i
FoundArg = FALSE
IF WScript.Arguments.Count <> 0 THEN
 r32i = 0
 thisArg = lcase(thisArg)
 DO
  IF lcase(WScript.Arguments(r32i)) = thisArg THEN FoundArg = True
  r32i = r32i + 1
 LOOP Until FoundArg OR r32i >= WScript.Arguments.Count
END IF
MatchAnyArg = FoundArg
End Function

Function RestartWithCScript32(extraargs)
Dim strCMD, iCount, r32wShell, r32fso
SET r32fso = CreateObject("Scripting.FileSystemObject")
SET r32wShell = WScript.CreateObject("WScript.Shell")
strCMD = r32wShell.ExpandEnvironmentStrings("%SYSTEMROOT%") & "\SysWOW64\cscript.exe"
If NOT r32fso.FileExists(strCMD) Then strCMD = "cscript.exe"
strCMD = strCMD & Chr(32) & Wscript.ScriptFullName & Chr(32)
If Wscript.Arguments.Count > 0 Then
 For iCount = 0 To WScript.Arguments.Count - 1
  if Instr(Wscript.Arguments(iCount), " ") = 0 Then ' add unspaced args
   strCMD = strCMD & " " & Wscript.Arguments(iCount) & " "
  Else
   If Instr("/-\", Left(Wscript.Arguments(iCount), 1)) > 0 Then ' quote spaced args
    If InStr(WScript.Arguments(iCount),"=") > 0 Then
     strCMD = strCMD & " " & Left(Wscript.Arguments(iCount), Instr(Wscript.Arguments(iCount), "=") ) & """" & Mid(Wscript.Arguments(iCount), Instr(Wscript.Arguments(iCount), "=") + 1) & """ "
    ElseIf Instr(WScript.Arguments(iCount),":") > 0 Then
     strCMD = strCMD & " " & Left(Wscript.Arguments(iCount), Instr(Wscript.Arguments(iCount), ":") ) & """" & Mid(Wscript.Arguments(iCount), Instr(Wscript.Arguments(iCount), ":") + 1) & """ "
    Else
     strCMD = strCMD & " """ & Wscript.Arguments(iCount) & """ "
    End If
   Else
    strCMD = strCMD & " """ & Wscript.Arguments(iCount) & """ "
   End If
  End If
 Next
End If
r32wShell.Run strCMD & " " & extraargs, 0, False
Set r32wShell = Nothing
SET r32fso = Nothing
End Function

' *******************
' *** END 64bit check
' *******************

Books Read 2025

Below are the books that I read during 2025 and my rating out of 5. Rating Title Author Book# 5 Flybot Dennis E. Taylor - 5 Here One Moment ...