Reputation: 158
How can I check out if registry key is link to another one using winapi?
For example, I need to find out which branch is original HKEY_LOCAL_MACHINE\SECURITY\SAM
or HKEY_LOCAL_MACHINE\SAM\SAM
, HKEY_CURRENT_USER
or HKEY_USERS\S-1-5-21
.
I'm confused with types of keys and values. Does key have type? Can I use REG_LINK
type for this purpose?
Upvotes: 1
Views: 1525
Reputation: 33734
First of all we must open the key itself, rather than the key that the potential symbolic link key refers to (which is the default behavior).
For this we need to use REG_OPTION_OPEN_LINK
option in call RegOpenKeyExW
or ZwOpenKeyEx
.
An alternative way is to use OBJ_OPENLINK
attribute in OBJECT_ATTRIBUTES
. and use this in call ZwOpenKey[Ex]
After the key is opened we can query (starting from win7) undocumented KeyFlagsInformation
information via ZwQueryKey
. If the flags shows that this is symbolic link - we can query SymbolicLinkValue
value to get the link target key. Note that even if this value exists with type REG_LINK
- this doesn't prove that this is symbolic link.
struct KEY_CONTROL_FLAGS_INFO_W7 // KeyFlagsInformation for Win7
{
ULONG ControlFlags[3];
};
#define KEY_CTRL_FL_W7_01__IS_VOLATILE 0x01
#define KEY_CTRL_FL_W7_01__SYM_LINK 0x02
LSTATUS IsSymLink(HKEY hKey, PCWSTR lpSubKey, BOOL& IsLink)
{
LSTATUS r = RegOpenKeyEx(hKey, lpSubKey, REG_OPTION_OPEN_LINK, KEY_READ|KEY_WOW64_64KEY, &hKey);
if (r == NOERROR)
{
ULONG Type, cb = 0, rcb = 0x80;
KEY_CONTROL_FLAGS_INFO_W7 kcf;
NTSTATUS status;
if (0 <= (status = ZwQueryKey(hKey, KeyFlagsInformation, &kcf, sizeof(kcf), &cb)))
{
if (kcf.ControlFlags[1] & KEY_CTRL_FL_W7_01__SYM_LINK)
{
IsLink = TRUE;
DbgPrint("key is link\n");
PVOID stack = alloca(guz), buf = 0;
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
r = RegQueryValueExW(hKey, L"SymbolicLinkValue", 0, &Type, (PBYTE)buf, &(rcb = cb));
if (r == NOERROR && Type == REG_LINK && !(rcb & (sizeof(WCHAR) - 1)))
{
DbgPrint("%.*S\n", rcb / sizeof(WCHAR), buf);
}
} while (r == ERROR_MORE_DATA);
}
}
else
{
r = RtlNtStatusToDosError(status);
}
RegCloseKey(hKey);
}
return r;
}
Does key have type?
No. type have values of key only
Can I use REG_LINK type for this purpose?
We can on a regular(not link) key create SymbolicLinkValue
value with type REG_LINK
, but key doesn't become a link after this. Key must be initially created with REG_OPTION_CREATE_LINK
option. So by querying SymbolicLinkValue
value we can't reliably check if this is a link, but if we know that this is a link - we can get the target of the link by querying SymbolicLinkValue
Upvotes: 4