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?
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?
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
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.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
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; } };
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
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
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law