|
easy to jump start my utility tool..
diligent hands rule....
|
|
|
|
|
Hy with the function WriteDword you must change only
REG_BINARY with REG_DWORD like below
if (::RegSetValueEx(hKey, LPCTSTR(strName), 0,
REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue)) // old value REG_BINARY
!= ERROR_SUCCESS) bSuccess = FALSE;
G3D
|
|
|
|
|
Bug in Unicode version of CRegistry::WriteString
should be
#ifdef _UNICODE
if (::RegSetValueEx(hKey, LPCTSTR(strName), 0,
REG_SZ, (LPBYTE)sz, (wcslen(sz) + 1) * sizeof(_TCHAR))
!= ERROR_SUCCESS) bSuccess = FALSE;
instead of
#ifdef _UNICODE
if (::RegSetValueEx(hKey, LPCTSTR(strName), 0,
REG_SZ, (LPBYTE)sz, wcslen(sz) + 1)
!= ERROR_SUCCESS) bSuccess = FALSE;
|
|
|
|
|
Is there any license limitation ?
|
|
|
|
|
Dear Robert, first thank's very much for share your code, nice Job,
I start to use it, and I need another functionaly, navigate trough subkeys, I add this fuctionaly to your class and I thing it's a good function to include in the article,
<br />
BOOL CRegistry::QuerySubKey(int index, CString& subkeyname) <br />
{ <br />
TCHAR achKey[MAX_KEY_LENGTH];
DWORD cbName;
TCHAR achClass[MAX_PATH] = TEXT("");
DWORD cchClassName = MAX_PATH;
DWORD cSubKeys=0;
DWORD cbMaxSubKey;
DWORD cchMaxClass;
DWORD cValues;
DWORD cchMaxValue;
DWORD cbMaxValueData;
DWORD cbSecurityDescriptor;
FILETIME ftLastWriteTime;
<br />
DWORD i, retCode; <br />
<br />
HKEY hKey;<br />
ASSERT(m_strCurrentPath.GetLength() > 0);<br />
<br />
if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,<br />
KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS) return FALSE;<br />
<br />
TCHAR achValue[MAX_VALUE_NAME]; <br />
DWORD cchValue = MAX_VALUE_NAME; <br />
<br />
retCode = RegQueryInfoKey(<br />
hKey,
achClass,
&cchClassName,
NULL,
&cSubKeys,
&cbMaxSubKey,
&cchMaxClass,
&cValues,
&cchMaxValue,
&cbMaxValueData,
&cbSecurityDescriptor,
&ftLastWriteTime);
<br />
<br />
if (cSubKeys)<br />
{<br />
if ((index < 0) || (index >= cSubKeys))<br />
return FALSE;<br />
<br />
cbName = MAX_KEY_LENGTH;<br />
retCode = RegEnumKeyEx(hKey, index,<br />
achKey, <br />
&cbName, <br />
NULL, <br />
NULL, <br />
NULL, <br />
&ftLastWriteTime); <br />
if (retCode == ERROR_SUCCESS) <br />
{<br />
subkeyname = achKey;<br />
}<br />
else<br />
return FALSE;<br />
}<br />
<br />
::RegCloseKey(hKey);<br />
<br />
return TRUE;<br />
}<br />
And a little example of how to use it:
<br />
m_reg.SetRootKey(HKEY_LOCAL_MACHINE);<br />
if (m_reg.SetKey("Software\\NFFormDestiller\\ExportDrivers", FALSE)) {<br />
for (int x = 0; x < m_reg.GetSubKeyCount(); x++) {<br />
CString subkey;<br />
if (m_reg.QuerySubKey(x, subkey)) {<br />
CRegistry reg;<br />
reg.SetRootKey(HKEY_LOCAL_MACHINE);<br />
if (reg.SetKey("Software\\NFFormDestiller\\ExportDrivers\\"+subkey, FALSE)) {<br />
CString desc = reg.ReadString("","");<br />
int index = m_lstcfg.InsertItem(x,desc,0);<br />
m_lstcfg.SetItemText(index,1,subkey);<br />
}<br />
}<br />
}<br />
}<br />
Best Regards
Rey
|
|
|
|
|
i cant believe noone has relied to this... vider, thank you so much for this addon (i couldnt use this class for what i wanted without it)! and of course, thank your Robert for the class/code. Excellent stuff.im coming from a C# background (im young, i know!), and code like this is making me realize how usable MFC can be, to the point where now i prefer it.
just wanted to again say thanks!
-daniel b
|
|
|
|
|
I tried to write Systems IP address into registry. When UNICODE is not defined then i could see the value from registry. And if Unicode is defined then i'm seeing 4 square boxed in the place of IP address..
How to show the IP address in the registry though UNICODE is defined?
Code snippet:
int main(void)
{
HKEY hKey;
char name[] = "199.68.56.33";
RegOpenKeyExW(HKEY_LOCAL_MACHINE,L"SOFTWARE\\MyCompany\\\\InstallInfo", 0, KEY_ALL_ACCESS, &hKey);
RegSetValueEx(hKey, L"FTEBaseIPAddress", 0, REG_SZ, name, ((strlen(name)+1)*sizeof(TCHAR)) );
return 1;
}
ssssssssssssssssssssssss
ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
|
|
|
|
|
I'm sorry about my poor english, but u shoud use _T("") rathor than L""
|
|
|
|
|
when enumerating the registry or passing across buffers is there a need to null terminate the buffer as shown below:
DWORD dwSize = MAX_PATH;
TCHAR szSubkeyName[MAX_PATH+1];
memset(szSubkeyName,0x00,sizeof(TCHAR)*(MAX_PATH+1));
while( RegEnumKeyEx(hKey,
dwIndex,
szSubkeyName,
&dwSize,
NULL,
NULL,
NULL,
&ftLastWriteTime) == ERROR_SUCCESS)
{
|
|
|
|
|
Hi Robert,
I hope you don't mind (and you are mentioned in it), but I took your excellent format of this class (CRegistry) and created a class that uses the nt.dll Native functions (e.g. NtCreateKey, NtDeleteKey, etc...). I did this because I have enjoyed you class for a long time and always use in apps that I write. I especially like the simplicity of it and that is why I adopted it for this new class I wrote "CNtRegistry" - link is below. Please take a look and let me know what you think?
There is a lot of added stuff in it like "Hiding Keys, Copying Keys/Values, Searching, Deleting recursively, etc...". I did this because I saw a lot of folks here asking for it.
http://www.codeproject.com/system/NtRegistry.asp[^]
Again, let me know what you think.
Regards,
Dan
|
|
|
|
|
I am trying to read a key of the type Binary, I do not see any function for this, The data is actually a person's name so I need to read a type Binary into a CSrting
Example: 44 00 6F 00 6E 00 20 00 4C 00 61 00 76 00 65 00 72 00 64 00 75 00 72 00 65
Converted=Don Laverdure
Any suggestions?
Cheers,
Don
|
|
|
|
|
|
Thanks for a useful class. It would be nice if WriteDword() specified REG_DWORD instead of REG_BINARY.
Jason
The question of whether computers can think is like the question of whether submarines can swim (Dijkstra)
|
|
|
|
|
|
Please note that there is a UNICODE bug in CRegistry::WriteString
the last parameter for RegSetValueEx should be number of bytes, NOT the existing number of characters, so it must be multiplied by sizeof(TCHAR) to fix it. It must also be cast to a DWORD to get rid of level 4 warnings.
Warren
|
|
|
|
|
There is a lot more to be fixed:
- change all LPSTR to LPCTSTR
- change strlen() to _tcslen()
- cast file.GetLength() to (DWORD)file.GetLength();
- change all char to TCHAR
This has to be done for all string handling routines, like ReadString, too.
Hope this will help..
|
|
|
|
|
I've noted that if you are a non-priviliged user and you want to read the Registry, you may encounter problem when you use CRegistry::KeyExists and CRegistry::SetKey.
This seems due to the fact that these methods call ::RegOpenKeyEx with KEY_ALL_ACCESS parameter. I've seen that if you use KEY_READ everything is ok.
I'm not familiar with Microsoft security access masks, MSDN says that KEY_ALL_ACCESS is a combination of KEY_READ, KEY_WRITE and KEY_CREATE_LINK but it is not clear whether the combination is AND or OR.
From this, it seems to me that KEY_ALL_ACCESS requires both read and write rights, the latter not being available to a non-priviliged user.
So, why KEY_ALL_ACCESS has been used for reading ? Isn't KEY_READ more appropriate ?
|
|
|
|
|
i agree. i would perhaps add a method for determining the current access level? i added this hack for my own program using this class.
|
|
|
|
|
if anyone is interested, here is my hack:
in protected section, i added
int m_Access;
i set this to KEY_ALL_ACCESS is the constructor.
then, i added these methods to the header file:
// changes current access level to KEY_READ.
void SetToReadAccess() { m_Access = KEY_READ; }
// changes current access level to KEY_WRITE.
void SetToWriteAccess() { m_Access = KEY_WRITE; }
// changes current access level to KEY_EXECUTE.
void SetToExecuteAccess() { m_Access = KEY_EXECUTE; }
// changes current access level to KEY_ALL_ACCESS. This is the default.
void SetToAllAccess() { m_Access = KEY_ALL_ACCESS; }
i thought this method, of the access being set by the last SetToAccess... call fit in with the way the rest of the class works (like, main and sub keys being remembered from the last set calls), and this avoids the user having to dig out the access constants in the winnt.h file. i excluded the specific access constants, and just went with these 4 that are combos of the original ones.
with this i am finally able to use this class, i am reading values set by the VCP FTDI USB-to-ComPort driver, and it wouldn't read with KEY_ALL_ACCESS privelages.
- daniel b
|
|
|
|
|
Thanks alot, thats exactly what I was looking for;)
|
|
|
|
|
Mr Robert, you made me ROBOT!!! No more words to utter!!!
cheers
Balkrishna Talele
|
|
|
|
|
This is an excellent piece of code Robert. It turned what was becoming a nightmarish task into a breeze! Thanks so much for sharing it!!
Karen
|
|
|
|
|
The original version limited textstrings to 255 characters, I needed more. I changed WriteString() and ReadString() to get what I wanted. The following doesn't have any limit and works well in Unicode too. This includes the code from my previous bugfix message.
BOOL CRegistry::WriteString(CString strName, CString strValue)
{
ASSERT(m_strCurrentPath.GetLength() > 0);
BOOL bSuccess = TRUE;
HKEY hKey;
if (::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
KEY_WRITE, &hKey) != ERROR_SUCCESS) return FALSE;
if (::RegSetValueEx( hKey,
LPCTSTR(strName),
NULL,
REG_SZ,
(LPBYTE) ( (const TCHAR*) strValue),
(strValue.GetLength()+1)*sizeof(TCHAR)
)
!= ERROR_SUCCESS) bSuccess = FALSE;
if (!m_bLazyWrite) ::RegFlushKey(hKey);
::RegCloseKey(hKey);
return bSuccess;
}
CString CRegistry::ReadString(CString strName, CString strDefault)
{
DWORD dwType = REG_SZ;
DWORD dwSize = 0;
BOOL bSuccess = TRUE;
HKEY hKey;
ASSERT(m_strCurrentPath.GetLength() > 0);
dwType = GetDataType(strName);
if (dwType != REG_SZ && dwType != REG_EXPAND_SZ)
{
return strDefault;
}
m_nLastError = ::RegOpenKeyEx(m_hRootKey, LPCTSTR(m_strCurrentPath), 0,
KEY_READ, &hKey);
if (m_nLastError != ERROR_SUCCESS) return strDefault;
::RegQueryValueEx( hKey,
LPCTSTR(strName),
NULL,
&dwType,
NULL,
&dwSize);
dwSize += sizeof(TCHAR);
TCHAR* sz = new TCHAR[ dwSize/sizeof(TCHAR) ];
m_nLastError = ::RegQueryValueEx( hKey,
LPCTSTR(strName),
NULL,
&dwType,
(LPBYTE)sz,
&dwSize);
CString retValue;
if(bSuccess)
retValue = sz;
delete [] sz;
if (m_nLastError != ERROR_SUCCESS) bSuccess = FALSE;
::RegCloseKey(hKey);
if (!bSuccess) return strDefault;
return retValue;
}
|
|
|
|
|
PEK wrote: The original version limited textstrings to 255 characters, I needed more. I changed WriteString() and ReadString()
Thank you so much. I had the same issue that solved by reading your post.
// "In the end it's a little boy expressing himself." Yanni
while (I_am_alive) { cout<<"I love to do more than just programming."; }
|
|
|
|
|
Is there anyway to enumerate Key and Value entries?
|
|
|
|
|