Given two HKEYs, original and copy, where copy is a copy of original obtained through RegOpenKeyEx by passing 0 as name, is there a way to find out if these two point to the same key?
Printable View
Given two HKEYs, original and copy, where copy is a copy of original obtained through RegOpenKeyEx by passing 0 as name, is there a way to find out if these two point to the same key?
Post a specific examples.
Do you want to comparehandle, pointer, or the actual string of the registry key?
Kuphryn
I don't think there is any reliable way to compare based on HKEY handles alone.
gg
Example. I have written an iterator over registry keys (Codeplug knows this).
The iterator essentially looks like this:
internal::regCopyKey just calls RegOpenKeyEx to copy the handle p into parent.Code:class reg_key_iterator {
// Used for RegEnumKeysEx
HKEY parent;
DWORD index;
public:
reg_key_iterator(HKEY p, DWORD i)
: index(i)
{
internal::regCopyKey(p, KEY_ALL_ACCESS, parent);
}
}
The problem is, if I create two iterators over the same key with this, I need to compare them, and parent == o.parent doesn't work, because the handles have different values.Code:::RegOpenKeyEx(in, 0, 0, sam, &out);
The iterator copies the key to avoid other objects closing the handle.
Is there a way I can find out if two HKEYs with distinct values point to the same key?
Thx in advance.
I noticed on my win2k box that the first copied handle was only 4 bytes off from the original handle value - probably don't want to count on that though.
First thing that comes to my mind is to keep track of the full "pathname" of the hive that reg_key_iterator is iterating over.
Or you could come up with a HKEY class that uses reference counting so you don't have to make copies, then use the HKEY in the comparison.
gg
I used the second solution. Is this shared_hkey correct?
Code:class shared_hkey {
HKEY key;
long *refcount;
public:
shared_hkey()
: key(0), refcount(0)
{
}
shared_hkey(HKEY h)
: key(h)
{
refcount = new long;
*refcount = 1;
}
shared_hkey(const shared_hkey &o)
: key(o.key), refcount(o.refcount)
{
if(refcount) {
++*refcount;
}
}
~shared_hkey() {
reset(0);
}
shared_hkey &operator =(const shared_hkey &o) {
if(o != *this) {
reset(0);
key = o.key;
refcount = o.refcount;
++*refcount;
}
return *this;
}
void reset(HKEY h) {
if(h != key && refcount) {
if(--*refcount == 0) {
delete refcount;
refcount = 0;
regCloseKey(key);
key = 0;
}
}
key = h;
if(key) {
refcount = new long;
*refcount = 1;
}
}
operator HKEY() const {
return key;
}
bool operator ==(const shared_hkey &o) {
return key == o.key;
}
bool operator !=(const shared_hkey &o) {
return key != o.key;
}
};
This will cause a memory leak:
Code:shared_hkey sk;
sk.reset((HKEY)5);
sk.reset((HKEY)5);
Some other recommendations:Code:void reset(HKEY h) {
if(key != h) {
// "detach" from our current key
if(refcount && --*refcount == 0) {
delete refcount;
refcount = 0;
regCloseKey(key);
}
//not really needed, but don't get warm fuzzies seeing it there
refcount = 0;
key = h;
if(key) {
refcount = new long;
*refcount = 1;
}
}
}//reset
Looks good.Code:bool operator ==(const shared_hkey &o) const {
bool operator !=(const shared_hkey &o) const {
gg
Thanks a lot. Works like a charm.
Now I need to get my dialog stream buffer properly working, but that's another project ;)