Who or what is Reggie?
Reggie was the project I decided to start working on about a year ago at the time of writing this, to overcome some shortfalls I had when dealing with the Windows Registry on a project our company was working on for the support team.
Your next question might be, why are you using GoLang to utilise such a task?
Well, we needed a small, compact CLI tool that our team could run repetitive tasks from to retrieve and interact with information quickly.
The registry wasn’t something we were planning to interact with in the beginning, but as the scope of the project grew so did the interaction. By this point the project was 3,000 lines deep and we didn’t feel the necessary need to rewrite the whole thing in another language. We wanted to see how far we could push Go at a system level rather than what it focuses and excels at: Web.
Surprisingly, it worked extremely well and most implementations of logic were very simple, with thanks to the std library being so well thought out.
The problem
So, on to the interesting part, our first mission was to implement fixes that commonly occurred on customer machines with MS Office. The most talked about problem: OST/PST files exceeding 50GB, Outlook’s max file size for mailbox storage. Yep, why and how were these mailboxes so large? We knew the resolution, which was applying a patch into the registry. Our first thought was, well, you can easily deploy registry data via Group Policy for domain joined machines, but for the most part, a lot of customers didn’t need or want AD infrastructure.
The second option is to use a PowerShell script, like so:
Third option, well, you guessed it, a REG file to just copy and open. But after discussing with the team, neither of these were preferred options because they require you to always have them on hand
and constantly copying them to client’s machines and deleting after. So this was the first problem we tackled, and we got it working perfectly, let’s call our tool ctl
:
That command will set Outlook’s max PST size to 70GB and patch it into the registry. It’s not flamboyant, but it works. The problem, however, was how we had to access the Registry:
Anyone familiar with Go can instantly see why this becomes a problem, especially if you’re accessing the Registry multiple times for other patches, which we did end up doing, quite a lot. I didn’t like having to constantly type the same thing over and over:
And then having to get whatever value, manipulate, maybe swap some keys, duplicate, set whatever you needed to. Point is, the implementation was always the same, and the usage was so barebones it was hard to write an interface around it, because we needed more functionality than just getting and setting. We needed ease of use, ways to traverse the registry, easy and clear definitions, preferably pointers to registry locations, so we could have clearly defined objects we would use within various scopes of the project without making it too hacky and reduce a lot of boilerplate.
Reggie
Now you can see why I decided I wanted a wrapper over the standard registry package. I’ll take some notes from the projects README to kickstart how Reggie works extremely well. Let’s take the standard definitions of the Registry package:
It’s long, a lot of error checking, having to manually get all the subkeys within the parent key you define, it’s a whole thing. However, Reggie’s definition is much simpler:
Beautiful work if I do say so myself. Let’s break this down, first I’ll show you the struct Reggie uses:
Starting out, we initialise:
The NewReg
function will initialise a struct containing the permission and an initialised SubKeyMap
which is just an empty make(map[string]*SubKey)
.
Once defined, you then supply the path and permission you want to start navigating:
Now we have a few possibilities as I wrote Reggie to have some utility, but in the provided example we use FillKeysValues()
:
This is propbably one of my favourite functions that I wrote. It’s ridiculously simple, you can see the full function by clicking here if you would like to see it. I’ll break it down quickly to save time though:
- Enumerate through all the subkeys in the parent key
- Generate an absolute path to every subkey
- Open each subkey
- Initialise a sub key map and push the data into a nested
&Reg
pointed struct - Read and get all values for each subkey and store them into the pointed struct
This can nest as deep as you want to go, it basically replicates the tree structure of the Registry. It looks like this:
So within just a few lines I’ve achieved pretty much everything without doing much of anything thanks to Reggie. This seriously came in handy with the cli tool we developed, and shortened our boiler plate code for Registry interactions by a huge margin, and made it far more readable.
I did think on writing a complete registry package from the ground up, but the standard one was just fine, it was dead simple, I just needed a better way to access everything, and Reggie provides that. It also retains all of the original package functions, so you can utilise both Reggie and the std package. All functions inside the package are exported, so any developer using the package can fine-tune it’s behaviour or do some magic via dependency injection if they wanted, hell it’s even open source so take it and do with it as they wish!
If you want to check out this project in full, you can head over to my projects and check it out for yourself.