Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 40 additions & 14 deletions std/windows/registry.d
Original file line number Diff line number Diff line change
Expand Up @@ -735,20 +735,21 @@ body
"Value cannot be set: \"" ~ subKey ~ "\"");
}

private void regProcessNthKey(HKEY hkey, scope void delegate(scope LONG delegate(DWORD, out string)) dg)
private void regProcessNthKey(Key key, scope void delegate(scope LONG delegate(DWORD, out string)) dg)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anything blocking? ;) - I'm not sure whether decorating the key param with scope makes a difference.

{
DWORD cSubKeys;
DWORD cchSubKeyMaxLen;

immutable res = regGetNumSubKeys(hkey, cSubKeys, cchSubKeyMaxLen);
immutable res = regGetNumSubKeys(key.m_hkey, cSubKeys, cchSubKeyMaxLen);
assert(res == ERROR_SUCCESS);

wchar[] sName = new wchar[cchSubKeyMaxLen + 1];

// Capture `key` in the lambda to keep the object alive (and so its HKEY handle open).
dg((DWORD index, out string name)
{
DWORD cchName;
immutable res = regEnumKeyName(hkey, index, sName, cchName);
immutable res = regEnumKeyName(key.m_hkey, index, sName, cchName);
if (res == ERROR_SUCCESS)
{
name = sName[0 .. cchName].to!string;
Expand All @@ -757,20 +758,21 @@ private void regProcessNthKey(HKEY hkey, scope void delegate(scope LONG delegate
});
}

private void regProcessNthValue(HKEY hkey, scope void delegate(scope LONG delegate(DWORD, out string)) dg)
private void regProcessNthValue(Key key, scope void delegate(scope LONG delegate(DWORD, out string)) dg)
{
DWORD cValues;
DWORD cchValueMaxLen;

immutable res = regGetNumValues(hkey, cValues, cchValueMaxLen);
immutable res = regGetNumValues(key.m_hkey, cValues, cchValueMaxLen);
assert(res == ERROR_SUCCESS);

wchar[] sName = new wchar[cchValueMaxLen + 1];

// Capture `key` in the lambda to keep the object alive (and so its HKEY handle open).
dg((DWORD index, out string name)
{
DWORD cchName;
immutable res = regEnumValueName(hkey, index, sName, cchName);
immutable res = regEnumValueName(key.m_hkey, index, sName, cchName);
if (res == ERROR_SUCCESS)
{
name = sName[0 .. cchName].to!string;
Expand Down Expand Up @@ -1388,7 +1390,7 @@ public:
string getKeyName(size_t index)
{
string name;
regProcessNthKey(m_key.m_hkey, (scope LONG delegate(DWORD, out string) getName)
regProcessNthKey(m_key, (scope LONG delegate(DWORD, out string) getName)
{
enforceSucc(getName(to!DWORD(index), name), "Invalid key");
});
Expand All @@ -1415,7 +1417,7 @@ public:
int opApply(scope int delegate(ref string name) dg)
{
int result;
regProcessNthKey(m_key.m_hkey, (scope LONG delegate(DWORD, out string) getName)
regProcessNthKey(m_key, (scope LONG delegate(DWORD, out string) getName)
{
for (DWORD index = 0; !result; ++index)
{
Expand Down Expand Up @@ -1485,7 +1487,7 @@ public:
Key getKey(size_t index)
{
string name;
regProcessNthKey(m_key.m_hkey, (scope LONG delegate(DWORD, out string) getName)
regProcessNthKey(m_key, (scope LONG delegate(DWORD, out string) getName)
{
enforceSucc(getName(to!DWORD(index), name), "Invalid key");
});
Expand All @@ -1512,7 +1514,7 @@ public:
int opApply(scope int delegate(ref Key key) dg)
{
int result = 0;
regProcessNthKey(m_key.m_hkey, (scope LONG delegate(DWORD, out string) getName)
regProcessNthKey(m_key, (scope LONG delegate(DWORD, out string) getName)
{
for (DWORD index = 0; !result; ++index)
{
Expand Down Expand Up @@ -1594,7 +1596,7 @@ public:
string getValueName(size_t index)
{
string name;
regProcessNthValue(m_key.m_hkey, (scope LONG delegate(DWORD, out string) getName)
regProcessNthValue(m_key, (scope LONG delegate(DWORD, out string) getName)
{
enforceSucc(getName(to!DWORD(index), name), "Invalid value");
});
Expand All @@ -1621,7 +1623,7 @@ public:
int opApply(scope int delegate(ref string name) dg)
{
int result = 0;
regProcessNthValue(m_key.m_hkey, (scope LONG delegate(DWORD, out string) getName)
regProcessNthValue(m_key, (scope LONG delegate(DWORD, out string) getName)
{
for (DWORD index = 0; !result; ++index)
{
Expand Down Expand Up @@ -1688,7 +1690,7 @@ public:
Value getValue(size_t index)
{
string name;
regProcessNthValue(m_key.m_hkey, (scope LONG delegate(DWORD, out string) getName)
regProcessNthValue(m_key, (scope LONG delegate(DWORD, out string) getName)
{
enforceSucc(getName(to!DWORD(index), name), "Invalid value");
});
Expand All @@ -1715,7 +1717,7 @@ public:
int opApply(scope int delegate(ref Value value) dg)
{
int result = 0;
regProcessNthValue(m_key.m_hkey, (scope LONG delegate(DWORD, out string) getName)
regProcessNthValue(m_key, (scope LONG delegate(DWORD, out string) getName)
{
for (DWORD index = 0; !result; ++index)
{
Expand Down Expand Up @@ -1840,3 +1842,27 @@ private:
auto e = collectException!RegistryException(HKCU.getKey("cDhmxsX9K23a8Uf869uB"));
assert(e.msg.endsWith(" (error 2)"));
}

@system unittest
{
Key HKCU = Registry.currentUser;
assert(HKCU);

Key key = HKCU.getKey("Control Panel");
assert(key);
assert(key.keyCount >= 2);

// Make sure `key` isn't garbage-collected while iterating over it.
// Trigger a collection in the first iteration and check whether we
// make it successfully to the second iteration.
int i = 0;
foreach (name; key.keyNames)
{
if (i++ > 0)
break;

import core.memory;
GC.collect();
}
assert(i == 2);
}