A while back I wrote a tool called NativeTest and open-sourced it on CodePlex. You can view the original post about this at the FSLogix Blog. Today I was troubleshooting a problem with registry links that required me to look at what was really going on in the registry, without it redirecting me through symbolic links. So I turned to the NativeTest project, which was able to help out.

For those who don’t already know, the registry can have symbolic links where a key actually is just a pointer to another key. So, for example, the HKLM\Software\CurrentControlSet key is a symbolic link created during system boot that points to HKLM\Software\CurrentControlSet001 (or some other numbered control set, depending on your hardware configuration).

Viewing a registry symbolic link involves opening the key with a special flag (REG_OPTION_OPEN_LINK) and then querying the value named “SymbolicLinkValue”. The value’s data will be a fully qualified native path to another registry key. The only difficult part about doing this with NativeTest is figuring out that the numeric option for REG_OPTION_OPEN_LINK is equivalent to 8, which you can find in the Windows SDK header files.

The NativeTest session for viewing the link at HKLM\System\ControlSet001\Control\Print\Printers is as follows:

> openkeyex -name \registry\machine\system\controlset001\control\print\printers -access kr -options 8
Status = 0x00000000
Handle = 40 (AUTO-0)

> enumvaluekey -handle AUTO-0 -index 0 -class full -bufferlen 256
AUTO-HANDLE: 40
Status = 0x00000000
ResultLength = 210
00 00 00 00 06 00 00 00     ........
38 00 00 00 9a 00 00 00     8.......
22 00 00 00 53 00 79 00     "...S.y.
6d 00 62 00 6f 00 6c 00     m.b.o.l.
69 00 63 00 4c 00 69 00     i.c.L.i.
6e 00 6b 00 56 00 61 00     n.k.V.a.
6c 00 75 00 65 00 46 00     l.u.e.F.
5c 00 52 00 65 00 67 00     \.R.e.g.
69 00 73 00 74 00 72 00     i.s.t.r.
79 00 5c 00 4d 00 61 00     y.\.M.a.
63 00 68 00 69 00 6e 00     c.h.i.n.
65 00 5c 00 53 00 6f 00     e.\.S.o.
66 00 74 00 77 00 61 00     f.t.w.a.
72 00 65 00 5c 00 4d 00     r.e.\.M.
69 00 63 00 72 00 6f 00     i.c.r.o.
73 00 6f 00 66 00 74 00     s.o.f.t.
5c 00 57 00 69 00 6e 00     \.W.i.n.
64 00 6f 00 77 00 73 00     d.o.w.s.
20 00 4e 00 54 00 5c 00      .N.T.\.
43 00 75 00 72 00 72 00     C.u.r.r.
65 00 6e 00 74 00 56 00     e.n.t.V.
65 00 72 00 73 00 69 00     e.r.s.i.
6f 00 6e 00 5c 00 50 00     o.n.\.P.
72 00 69 00 6e 00 74 00     r.i.n.t.
5c 00 50 00 72 00 69 00     \.P.r.i.
6e 00 74 00 65 00 72 00     n.t.e.r.
73 00                       s.

> closekey -handle auto-0
AUTO-HANDLE: 40
Status = 0x00000000

As you can see, this key is really just a pointer to HKLM\Software\Microsoft\Windows NT\CurrentVersion\Print\Printers.

The next task is how can I actually create one of these links for my own testing, just so I don’t accidentally mess up one of the system keys. Creating a symbolic registry link is pretty easy. You just have to create they key with a certain option (REG_OPTION_CREATE_LINK), and then set the value named “SymbolicLinkValue”, which needs to be of type REG_LINK. Again, the hard part is figuring out that REG_OPTION_CREATE_LINK is the equivalent of 2.

The session looks like this:

> createkey -name \registry\machine\software\Test -access ka -options 2
Status = 0x00000000
Disposition = Created
Handle = 48 (AUTO-0)

> setvaluekey -handle auto-0 -name SymbolicLinkValue -type link -data \\Registry\\Machine\\Software\\Test2
AUTO-HANDLE: 48
Status = 0x00000000

> queryvaluekey -handle auto-0 -name SymbolicLinkValue -class full -bufferlen 512
AUTO-HANDLE: 48
Status = 0x00000000
ResultLength = 120
00 00 00 00 06 00 00 00     ........
38 00 00 00 44 00 00 00     8...D...
22 00 00 00 53 00 79 00     "...S.y.
6d 00 62 00 6f 00 6c 00     m.b.o.l.
69 00 63 00 4c 00 69 00     i.c.L.i.
6e 00 6b 00 56 00 61 00     n.k.V.a.
6c 00 75 00 65 00 00 00     l.u.e...
5c 00 52 00 65 00 67 00     \.R.e.g.
69 00 73 00 74 00 72 00     i.s.t.r.
79 00 5c 00 4d 00 61 00     y.\.M.a.
63 00 68 00 69 00 6e 00     c.h.i.n.
65 00 5c 00 53 00 6f 00     e.\.S.o.
66 00 74 00 77 00 61 00     f.t.w.a.
72 00 65 00 5c 00 46 00     r.e.\.T.
53 00 4c 00 6f 00 67 00     e.s.t.2.

> closekey -handle auto-0
AUTO-HANDLE: 48
Status = 0x00000000

Once you have created it, it’s kind of fun to poke around at the key with regedit. If you, like me, decide to clean up your test key and delete it in regedit, you will find that deleting the link source actually follows the link and deletes the target. The link source remains and now displays an error about the system cannot find the file specified. In my testing, it seems to be impossible to delete the link source in regedit, so we need to look at one more thing in NativeTest: deleting the link source key. The only trick here is that you have to open the key with REG_OPTION_OPEN_LINK so that the system doesn’t try to follow the link (which, incidentally is what regedit is doing).

The session looks like this:

> openkeyex -name \registry\machine\software\test -access ka -options 8
Status = 0x00000000
Handle = 52 (AUTO-0)

> deletekey -handle auto-0
AUTO-HANDLE: 52
Status = 0x00000000

> closekey -handle auto-0
AUTO-HANDLE: 52
Status = 0x00000000

Windows Installer stores information about components, products, etc. that are installed on the system in the registry. Most of these elements are identified by a GUID, but the Installer doesn’t always store the GUID directly in the registry. Instead it uses what I call SQUIDs, or Squished GUIDs. Basically they just reformat the GUID a bit and remove some of the extra characters that don’t add anything (hyphens and braces). You can read more about this here: A Brief Note on Installer GUIDs.

Periodically when I am working on some installer code I can end up needing to search the registry for stuff that is related to a component I am working on. It is very helpful to be able to convert between SQUIDs and GUIDs. I usually just do this by hand, but today I decided I needed a bit more help doing this and wrote a tiny vbscript piece of code that does the conversion. On the chance that it might provide value for someone else, I have decided to post it here.

Function SquidToGuid(s)
  SquidToGuid = _
    StrReverse(Mid(s, 1, 8)) & "-" & _
    StrReverse(Mid(s, 9, 4)) & "-" & _
    StrReverse(Mid(s, 13, 4)) & "-" & _
    StrReverse(Mid(s, 17, 2)) & StrReverse(Mid(s, 19, 2)) & "-" & _
    StrReverse(Mid(s, 21, 2)) & StrReverse(Mid(s, 23, 2)) & StrReverse(Mid(s, 25, 2)) & _
    StrReverse(Mid(s, 27, 2)) & StrReverse(Mid(s, 29, 2)) & StrReverse(Mid(s, 31, 2))
End Function

Function GuidToSquid(g)
  Replace g, "{", ""
  Replace g, "}", ""
  GuidToSquid = _
    StrReverse(Mid(g, 1, 8)) & _
    StrReverse(Mid(g, 10, 4)) & _
    StrReverse(Mid(g, 15, 4)) & _
    StrReverse(Mid(g, 20, 2)) & StrReverse(Mid(g, 22, 2)) & _
    StrReverse(Mid(g, 25, 2)) & StrReverse(Mid(g, 27, 2)) & StrReverse(Mid(g, 29, 2)) & _
    StrReverse(Mid(g, 31, 2)) & StrReverse(Mid(g, 33, 2)) & StrReverse(Mid(g, 35, 2))
End Function