Index: reactos/sdk/lib/atl/atlbase.cpp =================================================================== --- reactos/sdk/lib/atl/atlbase.cpp (revision 72030) +++ reactos/sdk/lib/atl/atlbase.cpp (working copy) @@ -28,4 +28,80 @@ CAtlWinModule _AtlWinModule = CAtlWinModule(); CAtlComModule _AtlComModule; -}; // namespace ATL +/*static*/ LONG CRegKey::DoDeleteKeyTree(HKEY hKey, LPCTSTR lpszKey) +{ + ATLASSERT(hKey); + ATLASSERT(lpszKey); + + // open the subkey + HKEY hSubKey; + LONG ret; + REGSAM samDesired = KEY_ALL_ACCESS | KEY_WOW64_64KEY; + ret = ::RegOpenKeyEx(hKey, lpszKey, 0, samDesired, &hSubKey); + if (ret != ERROR_SUCCESS) + { + ret = ::RegOpenKeyEx(hKey, lpszKey, 0, KEY_ALL_ACCESS, &hSubKey); + } + if (ret != ERROR_SUCCESS) + { + return ret; + } + + // get the longest length of subkey names + DWORD NameMax; + ret = ::RegQueryInfoKey(hSubKey, NULL, NULL, NULL, NULL, + &NameMax, NULL, NULL, NULL, + NULL, NULL, NULL); + if (ret != ERROR_SUCCESS) + { + ::RegCloseKey(hSubKey); + return ret; // failure + } + ++NameMax; // for NUL + + // allocate the string buffer for names if necessary + TCHAR szNameBuf[MAX_PATH], *pszName; + if (NameMax > MAX_PATH) + { + pszName = new TCHAR[NameMax]; + ATLASSERT(pszName); + } + else + { + NameMax = MAX_PATH; + pszName = szNameBuf; + } + + // enumerate every subkey and delete + for (;;) + { + DWORD Count = NameMax; + LONG result = ::RegEnumKeyEx(hSubKey, 0, pszName, &Count, NULL, + NULL, NULL, NULL); + if (result != ERROR_SUCCESS) + { + break; + } + + ret = CRegKey::DoDeleteKeyTree(hSubKey, pszName); + if (ret != ERROR_SUCCESS) + { + break; + } + } + + // close subkey + ::RegCloseKey(hSubKey); + + // delete the subkey + if (ret == ERROR_SUCCESS) + ret = ::RegDeleteKey(hKey, lpszKey); + + // delete the buffer + if (pszName != szNameBuf) + delete[] pszName; + + return ret; +} // CRegKey::DoDeleteKeyTree + +} // namespace ATL Index: reactos/sdk/lib/atl/atlbase.h =================================================================== --- reactos/sdk/lib/atl/atlbase.h (revision 72030) +++ reactos/sdk/lib/atl/atlbase.h (working copy) @@ -53,6 +53,10 @@ #define ATL_NO_VTABLE __declspec(novtable) #endif +#ifndef ATL_DEPRECATED + #define ATL_DEPRECATED __declspec(deprecated) +#endif + #define offsetofclass(base, derived) (reinterpret_cast(static_cast(reinterpret_cast(_ATL_PACKING))) - _ATL_PACKING) namespace ATL @@ -1236,7 +1240,376 @@ return hResult; } +// registry key +class CRegKey +{ +public: + HKEY m_hKey; +#if 0 + // FIXME & TODO: + CAtlTransactionManager* m_pTM; +#endif + +public: + CRegKey() throw() : m_hKey(NULL) + { + } + CRegKey(CRegKey& key) throw() + { + m_hKey = key.Detach(); + } + explicit CRegKey(HKEY hKey) throw() + { + m_hKey = hKey; + } + +#if 0 + // FIXME & TODO: + CRegKey(CAtlTransactionManager* pTM) throw(); +#endif + + ~CRegKey() throw() + { + Close(); + } + +public: + void Attach(HKEY hKey) throw() + { + Close(); + m_hKey = hKey; + } + HKEY Detach() throw() + { + HKEY hKey = m_hKey; + m_hKey = NULL; + return hKey; + } + + operator HKEY() const throw() + { + return m_hKey; + } + + CRegKey& operator=(CRegKey& key) throw() + { + Attach(key.Detach()); + return *this; + } + +public: + // open/create/close + LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName, + REGSAM samDesired = KEY_READ | KEY_WRITE) throw() + { + ATLASSERT(hKeyParent); + ATLASSERT(lpszKeyName); + Close(); + LONG ret; + ret = ::RegOpenKeyEx(hKeyParent, lpszKeyName, 0, + samDesired | KEY_WOW64_64KEY, &m_hKey); + if (ret == ERROR_SUCCESS) + return ret; + ret = ::RegOpenKeyEx(hKeyParent, lpszKeyName, 0, samDesired, &m_hKey); + return ret; + } + + 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); + Close(); + LONG ret; + ret = ::RegCreateKeyEx(hKeyParent, lpszKeyName, 0, lpszClass, + dwOptions, samDesired | KEY_WOW64_64KEY, + lpSecAttr, &m_hKey, lpdwDisposition); + if (ret == ERROR_SUCCESS) + return ret; + ret = ::RegCreateKeyEx(hKeyParent, lpszKeyName, 0, lpszClass, + dwOptions, samDesired, lpSecAttr, &m_hKey, + lpdwDisposition); + return ret; + } + + LONG Close() throw() + { + LONG ret; + if (m_hKey) + { + ret = ::RegCloseKey(m_hKey); + m_hKey = NULL; + } + else + { + ret = ERROR_INVALID_HANDLE; + } + return ret; + } + + // set key value + LONG SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, + LPCTSTR lpszValueName = NULL) throw() + { + ATLASSERT(m_hKey); + return CRegKey::SetValue(m_hKey, lpszKeyName, lpszValue, lpszValueName); + } + + // delete value + LONG DeleteValue(LPCTSTR lpszValue) throw() + { + ATLASSERT(m_hKey); + LONG ret = ::RegDeleteValue(m_hKey, lpszValue); + return ret; + } + + // delete key + LONG DeleteSubKey(LPCTSTR lpszSubKey) throw() + { + ATLASSERT(m_hKey); + ATLASSERT(lpszSubKey); + LONG ret = ::RegDeleteKey(m_hKey, lpszSubKey); + return ret; + } + LONG RecurseDeleteKey(LPCTSTR lpszKey) throw() + { + return CRegKey::DoDeleteKeyTree(m_hKey, lpszKey); + } + + // enumerate key + 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; + } + + // security + 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; + } + + // query value + LONG QueryValue(LPCTSTR pszValueName, DWORD* pdwType, + void* pData, ULONG* pnBytes) throw() + { + ATLASSERT(m_hKey); + LONG ret; + ret = ::RegQueryValueEx(m_hKey, pszValueName, NULL, pdwType, + reinterpret_cast(pData), pnBytes); + return ret; + } + LONG QueryBinaryValue(LPCTSTR pszValueName, void* pValue, + ULONG* pnBytes) throw() + { + return QueryValue(pszValueName, NULL, pValue, pnBytes); + } + LONG QueryDWORDValue(LPCTSTR pszValueName, DWORD& dwValue) throw() + { + DWORD dwSize = sizeof(DWORD); + return QueryValue(pszValueName, NULL, &dwValue, &dwSize); + } + LONG QueryGUIDValue(LPCTSTR pszValueName, GUID& guidValue) throw() + { + DWORD dwSize = sizeof(GUID); + return QueryValue(pszValueName, NULL, &guidValue, &dwSize); + } + LONG QueryMultiStringValue(LPCTSTR pszValueName, LPTSTR pszValue, + ULONG* pnChars) throw() + { + *pnChars *= sizeof(TCHAR); + LONG ret; + ret = QueryValue(pszValueName, NULL, pszValue, pnChars); + *pnChars /= sizeof(TCHAR); + return ret; + } + LONG QueryQWORDValue(LPCTSTR pszValueName, ULONGLONG& qwValue) throw() + { + DWORD dwSize = sizeof(ULONGLONG); + return QueryValue(pszValueName, NULL, &qwValue, &dwSize); + } + LONG QueryStringValue(LPCTSTR pszValueName, LPTSTR pszValue, + ULONG* pnChars) throw() + { + *pnChars *= sizeof(TCHAR); + LONG ret; + ret = QueryValue(pszValueName, NULL, pszValue, pnChars); + *pnChars /= sizeof(TCHAR); + return ret; + } + ATL_DEPRECATED LONG QueryValue(DWORD& dwValue, LPCTSTR lpszValueName) + { + ATLASSERT(m_hKey); + BYTE *pbValue = reinterpret_cast(&dwValue); + DWORD cbValue = sizeof(DWORD); + LONG ret; + ret = ::RegQueryValueEx(m_hKey, lpszValueName, NULL, NULL, + pbValue, &cbValue); + return ret; + } + ATL_DEPRECATED LONG QueryValue(LPTSTR szValue, LPCTSTR lpszValueName, + DWORD* pdwCount) + { + ATLASSERT(m_hKey); + BYTE *pbValue = reinterpret_cast(szValue); + LONG ret; + *pdwCount *= sizeof(TCHAR); + ret = ::RegQueryValueEx(m_hKey, lpszValueName, NULL, NULL, + pbValue, pdwCount); + *pdwCount /= sizeof(TCHAR); + return ret; + } + + // setting value + LONG SetValue(LPCTSTR pszValueName, DWORD dwType, const void* pValue, + ULONG nBytes) throw() + { + ATLASSERT(m_hKey); + const BYTE *pbValue = reinterpret_cast(pValue); + LONG ret; + ret = ::RegSetValueEx(m_hKey, pszValueName, 0, dwType, pbValue, nBytes); + return ret; + } + LONG SetBinaryValue(LPCTSTR pszValueName, const void* pValue, + ULONG nBytes) throw() + { + return SetValue(pszValueName, REG_BINARY, pValue, nBytes); + } + LONG SetDWORDValue(LPCTSTR pszValueName, DWORD dwValue) throw() + { + ULONG dwSize = sizeof(DWORD); + return SetValue(pszValueName, REG_DWORD, &dwValue, dwSize); + } + LONG SetGUIDValue(LPCTSTR pszValueName, const GUID *guidValue) throw() + { + ULONG dwSize = sizeof(GUID); + return SetValue(pszValueName, REG_BINARY, guidValue, dwSize); + } + LONG SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue) throw() + { + ULONG dwSize = CRegKey::GetMultiStringSize(pszValue); + return SetValue(pszValueName, REG_QWORD, pszValue, dwSize); + } + LONG SetQWORDValue(LPCTSTR pszValueName, ULONGLONG qwValue) throw() + { + ULONG dwSize = sizeof(ULONGLONG); + return SetValue(pszValueName, REG_QWORD, &qwValue, dwSize); + } + LONG SetStringValue(LPCTSTR pszValueName, LPCTSTR pszValue, + DWORD dwType = REG_SZ) throw() + { + ULONG dwSize = (::lstrlen(pszValue) + 1) * sizeof(TCHAR); + return SetValue(pszValueName, dwType, pszValue, dwSize); + } + ATL_DEPRECATED LONG SetValue(DWORD dwValue, LPCTSTR lpszValueName) + { + ATLASSERT(m_hKey); + BYTE *pbData = reinterpret_cast(&dwValue); + DWORD cbData = sizeof(DWORD); + LONG ret; + ret = ::RegSetValueEx(m_hKey, lpszValueName, 0, REG_DWORD, + pbData, cbData); + return ret; + } + ATL_DEPRECATED LONG + SetValue(LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL, + bool bMulti = false, int nValueLen = -1) + { + ATLASSERT(m_hKey); + DWORD cbData, dwType; + if (bMulti) + { + cbData = CRegKey::GetMultiStringSize(lpszValue); + dwType = REG_MULTI_SZ; + } + else + { + dwType = REG_SZ; + if (nValueLen == -1) + cbData = ::lstrlen(lpszValue) * sizeof(TCHAR); + else + cbData = nValueLen * sizeof(TCHAR); + } + const BYTE *pbData = reinterpret_cast(lpszValue); + LONG ret; + ret = ::RegSetValueEx(m_hKey, lpszValueName, 0, dwType, pbData, cbData); + return ret; + } + + 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; + } + +public: + static LONG WINAPI + SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName, + LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL) + { + ATLASSERT(hKeyParent); + ATLASSERT(lpszKeyName); + HKEY hKey; + LONG ret; + ret = ::RegOpenKeyEx(hKeyParent, lpszKeyName, 0, KEY_ALL_ACCESS, &hKey); + if (ret != ERROR_SUCCESS) + return ret; + + const BYTE *pbData = reinterpret_cast(lpszValue); + DWORD cbData = (::lstrlen(lpszValue) + 1) * sizeof(TCHAR); + ret = ::RegSetValueEx(hKey, lpszValueName, 0, REG_SZ, + pbData, cbData); + ::RegCloseKey(hKey); + return ret; + } + +protected: + // get the total size of a multistring + static ULONG GetMultiStringSize(LPCTSTR pszz) + { + int count = 0; + do + { + int len = ::lstrlen(pszz); + count += len + 1; + pszz += len + 1; + } while (*pszz != TEXT('\0')); + ++count; + return count * sizeof(TCHAR); + } + + // delete key recursively + static LONG DoDeleteKeyTree(HKEY hKey, LPCTSTR lpszKey); +}; // class CRegKey + }; // namespace ATL #ifndef _ATL_NO_AUTOMATIC_NAMESPACE