Advanced Installer – Editing Any User’s Registry

There are scenarios when you want to change the registry settings of a user other than currently logged on. A typical example is Windows Service which may run under different credentials. While it’s easy to edit the registry of current user, for any other user there is no easy way out in Adavanced Installer. Though, it’s lot easier to achieve when look at the basics of HKEY_CURRENT_USER and HKEY_USERS.

Each registry key located under the HKEY_USERS hive corresponds to a user on the system and is named with that user’s security identifier, or SID. The registry keys and registry values located under each SID control settings specific to that user, like mapped drives, installed printers, desktop background, and much more.

Here is an example of what you might find under the HKEY_USERS hive:

  • HKEY_USERS\.DEFAULT
  • HKEY_USERS\S-1-5-18
  • HKEY_USERS\S-1-5-19
  • HKEY_USERS\S-1-5-20
  • HKEY_USERS\S-1-5-21-1055851958-2943780574-2716455932-1001
  • HKEY_USERS\S-1-5-21-1055851958-2943780574-2716455932-1001_Classes

The HKEY_CURRENT_USER hive acts as a kind of shortcut to the HKEY_USERS sub-key corresponding to your SID. In other words, when you make changes in HKEY_CURRENT_USER, you’re making changes to the keys and values under the key within HKEY_USERS that’s named the same as your SID.

01

For example, if your SID is S-1-5-21-1055851958-2943780574-2716455932-1001, HKEY_CURRENT_USER will point to HKEY_USERS\S-1-5-21-1055851958-2943780574-2716455932-1001. Edits can be made in either location since they are one in the same.

02

Now the next logical question is how to find out SID for a given username in C#.

You have an easy way out with .NET 2.0 and above:

NTAccount f = new NTAccount("username");
SecurityIdentifier s = (SecurityIdentifier) f.Translate(typeof(SecurityIdentifier));
String sidString = s.ToString();

But if you are stuck on something like .Net 1.1 (and believe me, most of the productions environments do). Here is the antidote.

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool LookupAccountName([In, MarshalAs(UnmanagedType.LPTStr)] string systemName,[In, MarshalAs(UnmanagedType.LPTStr)] string accountName, IntPtr sid, ref int cbSid, StringBuilder referencedDomainName, ref int cbReferencedDomainName, out int use);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool ConvertSidToStringSid(IntPtr sid,[In, Out, MarshalAs(UnmanagedType.LPTStr)] ref string pStringSid);
/// <summary>The method converts object name (user, group) into SID string.</summary>
/// <param name="name">Object name in form domainobject_name.</param>
/// <returns>SID string.</returns>
public static string GetSid(string name)
{
 IntPtr _sid = IntPtr.Zero; //pointer to binary form of SID string.
 int _sidLength = 0; //size of SID buffer.
 int _domainLength = 0; //size of domain name buffer.
 int _use; //type of object.
 StringBuilder _domain = new StringBuilder(); //stringBuilder for domain name.
 int _error = 0;
 string _sidString = "";
 //first call of the function only returns the sizes of buffers (SDI, domain name)
 LookupAccountName(null, name, _sid, ref _sidLength, _domain, ref _domainLength, out _use);
 _error = Marshal.GetLastWin32Error();
 if (_error != 122) //error 122 (The data area passed to a system call is too small) - normal behaviour.
 {
 throw(new Exception(new Win32Exception(_error).Message));
 }
 else
 {
 _domain = new StringBuilder(_domainLength); //allocates memory for domain name
 _sid = Marshal.AllocHGlobal(_sidLength); //allocates memory for SID
 bool _rc = LookupAccountName(null, name, _sid, ref _sidLength, _domain, ref _domainLength, out _use);
 if (_rc == false) {
 _error = Marshal.GetLastWin32Error();
 Marshal.FreeHGlobal(_sid);
 throw(new Exception(new Win32Exception(_error).Message));
 }
 else
 {
 // converts binary SID into string
 _rc = ConvertSidToStringSid(_sid, ref _sidString);
 if (_rc == false)
 {
 _error = Marshal.GetLastWin32Error();
 Marshal.FreeHGlobal(_sid);
 throw(new Exception(new Win32Exception(_error).Message));
 }
 else
 {
 Marshal.FreeHGlobal(_sid);
 return _sidString;
 }
 }
 }
}

With this essentials in place, you can easily create a custom action in Advanced Installer to plug in this functinality.

03

Advanced Installer – It makes sense

I have been writing code since 1997. Better part of these 15 years is spent on enterprise development and server side code. I had my share of WinForms development, but it was far and few. Even in these assignments, I don’t recall working on an installer project. Recently, I got the opportunity to work on one. The client wanted to migrate to a better platform than the current Visual Studio Setup Project. The tricky part was the deployment landscape. Half of the solution was to run on a Windows Sever (2008/2008R2/2012/2012R2) and rest of the story was in SharePoint On-premise (2010/2013).

In our journey, we evaluated a few options.

WiX (http://wixtoolset.org/)

Being a Microsoft’s Open Source alternative, WiX seemed a logical choice. It is an XML based framework to declare and compile MSI packages. Driven by MS employees, it is quiet a mature tool. But, primary issues with WiX are:

  1. It’s difficult to learn.
  2. There is no UI to speak off. You are confined to your favorite XML editor. It is very limiting at times. Even simple tasks like configuring a few registry entries can take a few hours.
  3. No direct support to SharePoint wsp deployments.

InstallShield (http://www.installshield.com/)

I remember Microsoft bundling InstallShield limited edition with Visual Studio until recently. But it is limiting option with no real support for complex deployment scenarios. It is suitable for a simple exe deployment on the target machine at best.

The latest product by Flexera Software, InstallAnywhere 2013 belongs to an entirely different league than the InstallShield Limited edition in terms for features. But it also lacked SharePoint deployment support. Oh, and did I mention the exorbitant pricing (starting with USD 2000 onwards).

Advanced Installer (http://www.advancedinstaller.com/)

Started around a decade back, Advanced Installer figured out that deploying any piece of software on windows has a huge reuse potential. They started putting together different software recipes to common problems like registry editing, conditional deployment of binaries based on x86/x64 platform, etc. They built easy to use interface on top of these recipes to control different parameters. And that was it. Really it’s that simple. This organic approach allowed Advanced Installer to build a nice Integrated Development Environment (IDE) to tie it up all. The advantages in this simple approach are many.

  1. Easy to learn.
  2. Out of the box features for common installation scenarios like registry editing, shortcut creation, course correction based on target platform (x86/x64) to name a few.
  3. Support for SharePoint wsp deployment.
  4. Support for custom development with the help of external functions packaged as .dll (in your favorite language).
  5. Everything goes back to .aip file which essentially is an XML file. Feel free to crack one open and do your build customizations.
  6. A responsive support forum.

You can figure out how simple this tool is based on following screenshots.

ai01

ai02

ai03

ai04

ai05

ai06

Advanced Installer provides a fully featured 30 day trail with licensing starting as low as USD 299. Needless to say we opted for it and happy with the decision.

Counterfeit Currency, Black Money and QR Codes

It seems a weird combination isn’t it. The first two seem related due to obvious reasons but how QR Code is related to it?

The answer is simple. Because in my humble opinion, QR Code is the technologies’ cure for these two.

If it’s still not obvious for you, indulge me for a few moments.

Anonymity – The hurting edge of this sword

We all know how great an innovation currency notes are. There is no reason to doubt it. Currency note are very powerful, not just because of the value but the anonymity that comes bundled with it. Every cash transaction is also an anonymous transaction. Most of the time the hands exchanging the cash know the value, reference and the consequences. Any other party (read Government) can know about it. As much for a solution, it becomes a problem when this tool is used against the good of the society. Terrorists, extremist, smugglers, drug dealers, extortionists, mafia, the list goes on and on; everybody uses cash and boy they love it. This love is more because of anonymity than value.

Stats
(Courtesy: Hindustan Times Dec 17, 2012)

Counterfeit – Clone to multiply

Counterfeit currency is big problem of the modern economy. Every money printing bank is coming up with security measures to fight this menace but somehow the crooks are winning. Watermarks, complex patterns, different textures, UV sensitive ink, metal foil strips, every trick in the book is tried and failed. Technology is too advanced and cheap these days for these measures to succeed.

Wait there is a serial number too. It is supposed to provide a unique identity to every note that is printed with it. But how do you verify the uniqueness of this number. Is there a mechanism for it? Is this mechanism fast, cheap, easily accessible to commoners?

The answer is a big NO.

Fake
(Photo by Chung Sung-Jun/Getty Images)

QR Codes – The Answer

Well print unique QR Codes on every currency note. It is a simple, fast and easily accessible solution for everyone to verify uniqueness and authenticity of a currency note. To make it work, some investments are required from the authorities in the form of fast QR Code scanners on the lines of currency counters. Every bank should scan the incoming notes’ QR Code for tracking and security purpose. This data should be consolidated at a central location and analyzed.

Machine

Answer to counterfeits

  1. No two note should carry the same QR codes. If they are, one of them is bogus.
  2. If two notes are scanned across different geo locations, in a short span of time, carrying the same QR Code, chances are one of them is rouge. Notes being physical objects can’t be teleported.
  3. Maintain and release a black list of such QR Codes. Withheld all such notes at banks, collect at central location and discard them.

Now imagine a smartphone app which allows you click a photo of the currency note(s). Scan the QR Code(s) on the fly and verify their authenticity in no time. How’s that for simplicity?

QRScanner

That’s not all, a pattern can be found out from the geo-locations of frequently fake reporting banks. It can help locate the centers of fake currency distributions.

Answer to black money

Tracking not only helps with fake but real money too. Let me run a few scenarios for you.

  1. A parent withdraws 20 lakhs from the bank and bribes a medical college for the admission of his incompetent son. The institute pays the same money to a building contractor. Contractor uses the same money to a low cost North Indian labor (no offence intended). The immigrant sends this money to his family back home. And the notes are scanned back at the bank/post office. Bingo!
  2. A private corporation pays for an expensive European honeymoon of a newly married daughter of a politician. Money changes hands but it originates from and lands in a bank some point time. Trace is complete and boom!

I don’t have to explain myself more. I think you got the point.

Why limit it to money only?

Really? If it’s that great a solution then why stop at money only. There are treasury bonds, stamp papers (ask Abdul Kareem Telgi), share certificates and many more avenues where QR codes can be an answer. It adds uniqueness to any valuable printed media and ends the ever dangerous anonymity with it.

Will it ever be implemented? I don’t think so. Why? Ask politicians, corrupt corporations and mafia of this word, they are more than willing to explain it to you :p