Author: mjansen
Date: Mon Oct 17 12:50:54 2016
New Revision: 72977
URL:
http://svn.reactos.org/svn/reactos?rev=72977&view=rev
Log:
[ATL][ATL_APITEST] Implementation / fixes for varions CRegKey functions, by Katayama
Hirofumi MZ. CORE-11746 #resolve
Modified:
trunk/reactos/sdk/lib/atl/atlbase.h
trunk/rostests/apitests/atl/CRegKey.cpp
Modified: trunk/reactos/sdk/lib/atl/atlbase.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/lib/atl/atlbase.h?rev=…
==============================================================================
--- trunk/reactos/sdk/lib/atl/atlbase.h [iso-8859-1] (original)
+++ trunk/reactos/sdk/lib/atl/atlbase.h [iso-8859-1] Mon Oct 17 12:50:54 2016
@@ -54,6 +54,10 @@
#define ATL_NO_VTABLE __declspec(novtable)
#endif
+#ifndef ATL_DEPRECATED
+#define ATL_DEPRECATED __declspec(deprecated)
+#endif
+
#define offsetofclass(base, derived)
(reinterpret_cast<DWORD_PTR>(static_cast<base *>(reinterpret_cast<derived
*>(_ATL_PACKING))) - _ATL_PACKING)
namespace ATL
@@ -891,6 +895,10 @@
{
public:
HKEY m_hKey;
+#if 0
+ // FIXME & TODO:
+ CAtlTransactionManager* m_pTM;
+#endif
public:
@@ -900,14 +908,22 @@
}
CRegKey(CRegKey& key) throw()
- {
- Attach(key.Detach());
+ : m_hKey(key.Detach())
+ {
}
explicit CRegKey(HKEY hKey) throw()
- :m_hKey(hKey)
- {
- }
+ : m_hKey(hKey)
+ {
+ }
+
+#if 0
+ // FIXME & TODO:
+ CRegKey(CAtlTransactionManager* pTM) throw()
+ {
+ ...
+ }
+#endif
~CRegKey() throw()
{
@@ -923,7 +939,7 @@
if (m_hKey)
{
HKEY hKey = Detach();
- return RegCloseKey(hKey);
+ return ::RegCloseKey(hKey);
}
return ERROR_SUCCESS;
}
@@ -935,11 +951,19 @@
return hKey;
}
- LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired = KEY_READ |
KEY_WRITE) throw()
- {
+ LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName,
+ REGSAM samDesired = KEY_READ | KEY_WRITE) throw()
+ {
+ ATLASSERT(hKeyParent);
+ ATLASSERT(lpszKeyName);
+
HKEY hKey = NULL;
-
- LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyName, NULL, samDesired, &hKey);
+ LONG lRes = ::RegOpenKeyEx(hKeyParent, lpszKeyName, NULL, samDesired,
&hKey);
+ if (lRes != ERROR_SUCCESS)
+ {
+ samDesired |= KEY_WOW64_64KEY;
+ lRes = ::RegOpenKeyEx(hKeyParent, lpszKeyName, NULL, samDesired, &hKey);
+ }
if (lRes == ERROR_SUCCESS)
{
Close();
@@ -948,11 +972,27 @@
return lRes;
}
- LONG Create(HKEY hKeyParent, LPCTSTR lpszKeyName, LPTSTR lpszClass = REG_NONE, DWORD
dwOptions = REG_OPTION_NON_VOLATILE, REGSAM samDesired = KEY_READ | KEY_WRITE,
LPSECURITY_ATTRIBUTES lpSecAttr = NULL, LPDWORD lpdwDisposition = NULL) throw()
- {
+ LONG Create(HKEY hKeyParent, LPCTSTR lpszKeyName,
+ LPTSTR lpszClass = REG_NONE,
+ DWORD dwOptions = REG_OPTION_NON_VOLATILE,
+ REGSAM samDesired = KEY_READ | KEY_WRITE,
+ LPSECURITY_ATTRIBUTES lpSecAttr = NULL,
+ LPDWORD lpdwDisposition = NULL) throw()
+ {
+ ATLASSERT(hKeyParent);
+ ATLASSERT(lpszKeyName);
+
HKEY hKey = NULL;
-
- LONG lRes = RegCreateKeyEx(hKeyParent, lpszKeyName, NULL, lpszClass, dwOptions,
samDesired, lpSecAttr, &hKey, lpdwDisposition);
+ LONG lRes = ::RegCreateKeyEx(hKeyParent, lpszKeyName, NULL, lpszClass,
+ dwOptions, samDesired, lpSecAttr, &hKey,
+ lpdwDisposition);
+ if (lRes != ERROR_SUCCESS)
+ {
+ samDesired |= KEY_WOW64_64KEY;
+ lRes = ::RegCreateKeyEx(hKeyParent, lpszKeyName, NULL, lpszClass,
+ dwOptions, samDesired, lpSecAttr, &hKey,
+ lpdwDisposition);
+ }
if (lRes == ERROR_SUCCESS)
{
Close();
@@ -961,10 +1001,10 @@
return lRes;
}
-
LONG QueryValue(LPCTSTR pszValueName, DWORD* pdwType, void* pData, ULONG* pnBytes)
throw()
{
- return RegQueryValueEx(m_hKey, pszValueName, NULL, pdwType, (LPBYTE)pData,
pnBytes);
+ ATLASSERT(m_hKey);
+ return ::RegQueryValueEx(m_hKey, pszValueName, NULL, pdwType, (LPBYTE)pData,
pnBytes);
}
LONG QueryDWORDValue(LPCTSTR pszValueName, DWORD& dwValue) throw()
@@ -996,7 +1036,7 @@
DWORD type = 0;
LONG lRet = QueryValue(pszValueName, &type, pszValue, &size);
- if (lRet == ERROR_SUCCESS && type != REG_SZ)
+ if (lRet == ERROR_SUCCESS && type != REG_SZ && type !=
REG_EXPAND_SZ)
lRet = ERROR_INVALID_DATA;
*pnChars = size / sizeof(TCHAR);
@@ -1022,15 +1062,42 @@
if (lRet != ERROR_SUCCESS)
return lRet;
- if (!SUCCEEDED(CLSIDFromString(buf, &guidValue)))
+ if (!SUCCEEDED(::CLSIDFromString(buf, &guidValue)))
return ERROR_INVALID_DATA;
return lRet;
}
+ LONG QueryQWORDValue(LPCTSTR pszValueName, ULONGLONG& qwValue) throw()
+ {
+ ULONG size = sizeof(ULONGLONG);
+ DWORD type = 0;
+ LONG lRet = QueryValue(pszValueName, &type, &qwValue, &size);
+
+ if (lRet == ERROR_SUCCESS && type != REG_QWORD)
+ lRet = ERROR_INVALID_DATA;
+
+ return lRet;
+ }
+
+ LONG QueryMultiStringValue(LPCTSTR pszValueName, LPTSTR pszValue,
+ ULONG* pnChars) throw()
+ {
+ ULONG size = (*pnChars) * sizeof(TCHAR);
+ DWORD type;
+ LONG lRet = QueryValue(pszValueName, &type, pszValue, &size);
+
+ if (lRet == ERROR_SUCCESS && type != REG_MULTI_SZ)
+ lRet = ERROR_INVALID_DATA;
+
+ *pnChars = size / sizeof(TCHAR);
+ return lRet;
+ }
+
LONG SetValue(LPCTSTR pszValueName, DWORD dwType, const void* pValue, ULONG nBytes)
throw()
{
- return RegSetValueEx(m_hKey, pszValueName, NULL, dwType, (const BYTE*)pValue,
nBytes);
+ ATLASSERT(m_hKey);
+ return ::RegSetValueEx(m_hKey, pszValueName, NULL, dwType, (const BYTE*)pValue,
nBytes);
}
LONG SetDWORDValue(LPCTSTR pszValueName, DWORD dwValue) throw()
@@ -1040,17 +1107,24 @@
LONG SetStringValue(LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwType = REG_SZ)
throw()
{
- if (dwType != REG_SZ)
- return ERROR_INVALID_DATA; // not implemented yet.
-
- ULONG length = (_tcslen(pszValue) + 1) * sizeof(TCHAR);
- return SetValue(pszValueName, dwType, pszValue, length);
+ ULONG length;
+ switch (dwType)
+ {
+ case REG_SZ:
+ case REG_EXPAND_SZ:
+ length = (_tcslen(pszValue) + 1) * sizeof(TCHAR);
+ return SetValue(pszValueName, dwType, pszValue, length);
+ case REG_MULTI_SZ:
+ return SetMultiStringValue(pszValueName, pszValue);
+ default:
+ return ERROR_INVALID_DATA;
+ }
}
LONG SetGUIDValue(LPCTSTR pszValueName, REFGUID guidValue) throw()
{
OLECHAR buf[40] = {0};
- StringFromGUID2(guidValue, buf, 39);
+ ::StringFromGUID2(guidValue, buf, 39);
#ifdef UNICODE
return SetStringValue(pszValueName, buf);
#else
@@ -1065,7 +1139,48 @@
return SetValue(pszValueName, REG_BINARY, pValue, nBytes);
}
- LONG SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName =
NULL) throw()
+ LONG SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue) throw()
+ {
+ ULONG dwSize = CRegKey::_GetMultiStringSize(pszValue);
+ return SetValue(pszValueName, REG_MULTI_SZ, pszValue, dwSize);
+ }
+
+ LONG SetQWORDValue(LPCTSTR pszValueName, ULONGLONG qwValue) throw()
+ {
+ ULONG dwSize = sizeof(ULONGLONG);
+ return SetValue(pszValueName, REG_QWORD, &qwValue, dwSize);
+ }
+
+ LONG NotifyChangeKeyValue(BOOL bWatchSubtree, DWORD dwNotifyFilter,
+ HANDLE hEvent, BOOL bAsync = TRUE) throw()
+ {
+ ATLASSERT(m_hKey);
+ LONG ret = ::RegNotifyChangeKeyValue(m_hKey, bWatchSubtree,
+ dwNotifyFilter, hEvent, bAsync);
+ return ret;
+ }
+
+ LONG Flush() throw()
+ {
+ ATLASSERT(m_hKey);
+ LONG ret = ::RegFlushKey(m_hKey);
+ return ret;
+ }
+
+ static LONG WINAPI SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName,
+ LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL)
+ {
+ CRegKey key;
+ LONG lRet = key.Create(hKeyParent, lpszKeyName);
+ if (lRet == ERROR_SUCCESS)
+ {
+ lRet = key.SetStringValue(lpszValueName, lpszValue);
+ }
+ return lRet;
+ }
+
+ LONG SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue,
+ LPCTSTR lpszValueName = NULL) throw()
{
CRegKey key;
LONG lRet = key.Create(m_hKey, lpszKeyName);
@@ -1078,12 +1193,47 @@
LONG DeleteValue(LPCTSTR lpszValue) throw()
{
- return RegDeleteValue(m_hKey, lpszValue);
+ ATLASSERT(m_hKey);
+ return ::RegDeleteValue(m_hKey, lpszValue);
}
LONG DeleteSubKey(LPCTSTR lpszSubKey) throw()
{
- return RegDeleteKey(m_hKey, lpszSubKey);
+ ATLASSERT(m_hKey);
+ ATLASSERT(lpszSubKey);
+ return ::RegDeleteKey(m_hKey, lpszSubKey);
+ }
+
+ LONG RecurseDeleteKey(LPCTSTR lpszKey) throw()
+ {
+ ATLASSERT(m_hKey);
+ ATLASSERT(lpszKey);
+ return CRegKey::_DoDeleteKeyTree(m_hKey, lpszKey);
+ }
+
+ LONG EnumKey(DWORD iIndex, LPTSTR pszName, LPDWORD pnNameLength,
+ FILETIME* pftLastWriteTime = NULL) throw()
+ {
+ ATLASSERT(m_hKey);
+ LONG ret = ::RegEnumKeyEx(m_hKey, iIndex, pszName, pnNameLength, NULL,
+ NULL, NULL, pftLastWriteTime);
+ return ret;
+ }
+
+ LONG GetKeySecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR psd,
+ LPDWORD pnBytes) throw()
+ {
+ ATLASSERT(m_hKey);
+ LONG ret = ::RegGetKeySecurity(m_hKey, si, psd, pnBytes);
+ return ret;
+ }
+
+ LONG SetKeySecurity(SECURITY_INFORMATION si,
+ PSECURITY_DESCRIPTOR psd) throw()
+ {
+ ATLASSERT(m_hKey);
+ LONG ret = ::RegSetKeySecurity(m_hKey, si, psd);
+ return ret;
}
operator HKEY() const throw()
@@ -1091,14 +1241,99 @@
return m_hKey;
}
- CRegKey& operator =(CRegKey& key) throw()
- {
- Attach(Detach());
+ CRegKey& operator=(CRegKey& key) throw()
+ {
+ Attach(key.Detach());
return *this;
}
-};
-
+protected:
+ // get the total size of a multistring
+ static ULONG _GetMultiStringSize(LPCTSTR pszz)
+ {
+ int count = 0;
+ do
+ {
+ int len = _tcslen(pszz);
+ count += len + 1;
+ pszz += len + 1;
+ } while (*pszz != TEXT('\0'));
+ ++count;
+ return count * sizeof(TCHAR);
+ }
+
+ // delete key recursively
+ static LONG _DoDeleteKeyTree(HKEY hParentKey, LPCTSTR lpszKey)
+ {
+ ATLASSERT(hParentKey);
+ ATLASSERT(lpszKey);
+
+ // open the key
+ CRegKey key;
+ LONG ret = key.Open(hParentKey, lpszKey);
+ if (ret != ERROR_SUCCESS)
+ {
+ return ret; // failure
+ }
+
+ // get the longest length of subkey names
+ DWORD NameMax;
+ ret = ::RegQueryInfoKey(key, NULL, NULL, NULL, NULL, &NameMax, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ if (ret != ERROR_SUCCESS)
+ {
+ return ret; // failure
+ }
+ ++NameMax; // for NUL
+
+ // allocate the string buffer for names if necessary
+ TCHAR szNameBuf[MAX_PATH], *pszName;
+ if (NameMax > MAX_PATH)
+ {
+ pszName = (TCHAR *)malloc(NameMax * sizeof(TCHAR));
+ ATLASSERT(pszName);
+ if (pszName == NULL)
+ {
+ return ERROR_OUTOFMEMORY; // failure
+ }
+ }
+ else
+ {
+ NameMax = MAX_PATH;
+ pszName = szNameBuf;
+ }
+
+ // enumerate every subkey and delete
+ for (;;)
+ {
+ DWORD Count = NameMax;
+ ret = key.EnumKey(0, pszName, &Count);
+ if (ret != ERROR_SUCCESS)
+ {
+ if (ret == ERROR_NO_MORE_ITEMS)
+ ret = ERROR_SUCCESS;
+ break;
+ }
+
+ ret = CRegKey::_DoDeleteKeyTree(key, pszName);
+ if (ret != ERROR_SUCCESS)
+ break;
+ }
+
+ // close key
+ key.Close();
+
+ // delete the subkey
+ if (ret == ERROR_SUCCESS)
+ ret = ::RegDeleteKey(hParentKey, lpszKey);
+
+ // delete the buffer if any
+ if (pszName != szNameBuf)
+ free(pszName);
+
+ return ret;
+ }
+};
template<class T>
class CComHeapPtr : public CHeapPtr<T, CComAllocator>
Modified: trunk/rostests/apitests/atl/CRegKey.cpp
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/atl/CRegKey.cpp?…
==============================================================================
--- trunk/rostests/apitests/atl/CRegKey.cpp [iso-8859-1] (original)
+++ trunk/rostests/apitests/atl/CRegKey.cpp [iso-8859-1] Mon Oct 17 12:50:54 2016
@@ -2,7 +2,8 @@
* PROJECT: ReactOS api tests
* LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
* PURPOSE: Test for CRegKey
- * PROGRAMMER: Mark Jansen
+ * PROGRAMMERS: Mark Jansen
+ * Katayama Hirofumi MZ (katayama.hirofumi.mz(a)gmail.com)
*/
#include <apitest.h>
@@ -185,4 +186,23 @@
lret = key.DeleteValue(_T("BIN_NAME"));
ok(lret == ERROR_SUCCESS, "Expected lret to be ERROR_SUCCESS, was: %lu\n",
lret);
+
+ {
+ CRegKey test1;
+ lret = test1.Create(HKEY_CURRENT_USER, _T("TEST1"));
+ ok(lret == ERROR_SUCCESS, "Expected lret to be ERROR_SUCCESS, was:
%lu\n", lret);
+
+ CRegKey test2;
+ lret = test2.Create(test1, _T("TEST2"));
+ ok(lret == ERROR_SUCCESS, "Expected lret to be ERROR_SUCCESS, was:
%lu\n", lret);
+
+ CRegKey test3;
+ lret = test3.Create(test2, _T("TEST3"));
+ ok(lret == ERROR_SUCCESS, "Expected lret to be ERROR_SUCCESS, was:
%lu\n", lret);
+ }
+ {
+ CRegKey key(HKEY_CURRENT_USER);
+ lret = key.RecurseDeleteKey(_T("TEST1"));
+ ok(lret == ERROR_SUCCESS, "Expected lret to be ERROR_SUCCESS, was:
%lu\n", lret);
+ }
}