Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

RegKey.h

Go to the documentation of this file.
00001 /*  RegKey.h - registry key wrappers
00002     Copyright (C) 2001-2004 Mark Weaver
00003     Written by Mark Weaver <mark@npsl.co.uk>
00004 
00005     Part of the Open-Win32 library.
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public
00017     License along with this library; if not, write to the
00018     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019     Boston, MA  02111-1307, USA.
00020 */
00021 
00026 #ifndef OW32_RegKey_h
00027 #define OW32_RegKey_h
00028 
00029 #include <OW32/XHKEY.h>
00030 #include <OW32/strconv.h>
00031 #include <OW32/auto_array_ptr.h>
00032 
00033 #include <cstring>
00034 #include <tchar.h>
00035 
00036 #ifndef OW32_NO_STL
00037 #include <string>
00038 #endif
00039 
00040 namespace OW32
00041 {
00042 
00044 class OW32_LIB_EXPORT CRegKey
00045 {
00046 private:
00047     CRegKey(const CRegKey& );
00048     CRegKey& operator=(const CRegKey& );
00049 
00050     XHKEY m_hKey;
00051 
00052     // helper functions to select the appropriate ANSI/UNICODE version of RegQueryValue based on the
00053     // output buffer's type
00054     LONG RegQueryString(LPCTSTR lpszValueName, LPDWORD pdwType, char* buf, LPDWORD pBufSize)
00055     {
00056         USES_CONVERSION;
00057         return RegQueryValueExA(m_hKey, T2CA(lpszValueName), NULL, pdwType, (LPBYTE)buf, pBufSize);
00058     }
00059 
00060     LONG RegQueryString(LPCTSTR lpszValueName, LPDWORD pdwType, wchar_t* buf, LPDWORD pBufSize)
00061     {
00062         USES_CONVERSION;
00063         return RegQueryValueExW(m_hKey, T2CW(lpszValueName), NULL, pdwType, (LPBYTE)buf, pBufSize);
00064     }
00065 
00066     template <class T>
00067     DWORD GrowBuffer(auto_array_ptr<T>* ppBuffer, DWORD curlen, bool copy = true, DWORD growby = 256)
00068     {
00069         DWORD lennew = curlen + growby;
00070         auto_array_ptr<T> pNew(new T[lennew]);
00071         if (copy) memcpy(pNew.get(), (*ppBuffer).get(), curlen * sizeof(T));
00072         *ppBuffer = pNew;
00073         return lennew;
00074     }
00075 
00076 public:
00078     CRegKey() 
00079     {
00080     }
00081 
00083     CRegKey(HKEY hKey) :
00084         m_hKey(hKey)
00085     {
00086     }
00087 
00089     void Close()
00090     {
00091         m_hKey.Close();
00092     }
00093 
00095     static inline IsStringType(DWORD dwType)
00096     {
00097         return dwType == REG_EXPAND_SZ || dwType == REG_MULTI_SZ || dwType == REG_SZ;
00098     }
00099 
00103     static inline IsDWORDType(DWORD dwType)
00104     {
00105         return dwType == REG_DWORD || dwType == REG_DWORD_LITTLE_ENDIAN || dwType == REG_DWORD_BIG_ENDIAN;
00106     }
00107 
00114     LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired = KEY_READ) 
00115     {
00116         Close();
00117         return RegOpenKeyEx(hKeyParent, lpszKeyName, 0, samDesired, &m_hKey);
00118     }
00119 
00120 #ifndef OW32_NO_STL
00121 
00129     template <class T>
00130     LONG QueryValue(std::basic_string<T>& strValue, LPCTSTR lpszValueName = NULL)
00131     {
00132         // initially use a quick query buffer
00133         T strBuf[MAX_PATH];
00134         DWORD BufSize = sizeof(strBuf);
00135 
00136         // do the query
00137         DWORD dwType;
00138         LONG lRet = RegQueryString(lpszValueName, &dwType, strBuf, &BufSize);
00139         if (lRet == ERROR_SUCCESS) 
00140         {
00141             // check type
00142             if (!IsStringType(dwType))
00143                 return ERROR_INVALID_DATATYPE;
00144 
00145             // trim trailing NULL if present.  RegQueryValueEx indicates that
00146             // we we may or may not get a NULL depending on what was stored in the
00147             // registry, and that we should do this checking here...
00148             DWORD nChars = BufSize/sizeof(T);
00149 
00150             if ((dwType == REG_EXPAND_SZ || dwType == REG_SZ) && nChars > 0)
00151             {
00152                 if (strBuf[nChars - 1] == T(0))
00153                     nChars--;
00154             } 
00155             else if (nChars >= 2) // REG_MULTI_SZ, trim final NULL
00156             {
00157                 if (strBuf[nChars - 1] == T(0) && strBuf[nChars - 2] == T(0))
00158                     nChars--;
00159             }
00160             strValue = std::basic_string<T>(strBuf, nChars);
00161             return ERROR_SUCCESS;
00162         }
00163 
00164         if (lRet != ERROR_MORE_DATA)
00165             return lRet;
00166 
00167         // value was too big - allocate a buffer of the correct size & retry
00168         DWORD nChars = BufSize/sizeof(T);
00169         auto_array_ptr<T> pBuf(new T[nChars]);
00170         lRet = RegQueryString(lpszValueName, &dwType, pBuf.get(), &BufSize);
00171 
00172         if (lRet == ERROR_SUCCESS) 
00173         {
00174             if (IsStringType(dwType))
00175             {
00176                 // Trim trailing NULL if present.  See note above.
00177                 DWORD nChars = BufSize/sizeof(T);
00178 
00179                 if ((dwType == REG_EXPAND_SZ || dwType == REG_SZ) && nChars > 0)
00180                 {
00181                     if (pBuf[nChars - 1] == T(0))
00182                         nChars--;
00183                 } 
00184                 else if (nChars >= 2) // REG_MULTI_SZ, trim final NULL
00185                 {
00186                     if (pBuf[nChars - 1] == T(0) && pBuf[nChars - 2] == T(0))
00187                         nChars--;
00188                 }
00189 
00190                 strValue = std::basic_string<T>(pBuf.get(), nChars);
00191             }
00192             else
00193             {
00194                 lRet = ERROR_INVALID_DATATYPE;
00195             }
00196         }
00197         return lRet;
00198     }
00199     
00206     template <class T>
00207     LONG EnumKey(DWORD index, std::basic_string<T>& name, FILETIME* pftime = NULL)
00208     {
00209         DWORD lenBuffer = 256;
00210         auto_array_ptr<T> pBuffer(new T[lenBuffer]);
00211 
00212         DWORD lenName = lenBuffer;
00213         FILETIME ftime;
00214         
00215         DWORD ret = 0;
00216         while((ret = ::RegEnumKeyEx(m_hKey, index, pBuffer.get(), &lenName, 0, NULL, NULL, pftime ? pftime : &ftime)) == ERROR_MORE_DATA)
00217         {
00218             // Grow buffer and try again
00219             lenBuffer = GrowBuffer(&pBuffer, lenBuffer, false);
00220             lenName = lenBuffer;
00221         }
00222 
00223         // Terminate & copy
00224         pBuffer[lenBuffer-1] = _T('\0');
00225         if (ERROR_SUCCESS == ret) {
00226             name = pBuffer.get();
00227         }
00228         return ret;
00229     }
00230 
00239     template <class T>
00240     LONG EnumValue(DWORD index, std::basic_string<T>& name, DWORD* pType = NULL, /*out*/BYTE** ppData = NULL, /*out*/DWORD* pLenData = NULL)
00241     {
00242         bool fWantData = ppData != NULL;
00243 
00244         DWORD lenNameBuffer = 256;
00245         auto_array_ptr<T> pNameBuffer(new T[lenNameBuffer]);
00246         
00247         DWORD lenDataBuffer = 256;
00248         auto_array_ptr<BYTE> pData;
00249         if (fWantData)
00250         {
00251             pData.reset(new BYTE[lenDataBuffer]);
00252         }
00253 
00254         DWORD lenName = lenNameBuffer;  
00255         DWORD lenData = lenDataBuffer;
00256 
00257         DWORD type = 0;
00258         DWORD ret = 0;
00259         while ((ret = ::RegEnumValue(m_hKey, index, pNameBuffer.get(), &lenName, 0, 
00260                 &type, fWantData ? pData.get() : NULL, fWantData ? &lenData : NULL)) == ERROR_MORE_DATA)
00261         {
00262             // Grow the name buffer and try again -- the name doesn't report it's actual
00263             // length, which is a bit irritating
00264             if (lenName >= lenNameBuffer) {
00265                 lenNameBuffer = GrowBuffer(&pNameBuffer, lenNameBuffer, false);
00266             }
00267             // If data is wanted, and was not all retrieved, then grow the data buffer and try and again
00268             if (fWantData && lenData > lenDataBuffer) {
00269                 lenDataBuffer = GrowBuffer(&pData, lenDataBuffer, false, lenData - lenDataBuffer);
00270             }
00271             lenName = lenNameBuffer;
00272         }
00273         
00274         if (ERROR_SUCCESS == ret) {
00275             // Terminate & copy name
00276             pNameBuffer[lenNameBuffer-1] = _T('\0');
00277             name = pNameBuffer.get();
00278 
00279             // outputs
00280             if (pLenData) *pLenData = lenData;
00281             if (ppData) *ppData = pData.release();
00282             if (pType) *pType = type;
00283 
00284         } else {
00285             // outputs
00286             if (pLenData) *pLenData = 0;
00287             if (ppData) *ppData = 0;
00288             if (pType) *pType = 0;
00289         }
00290         return ret;
00291     }
00292 #endif
00293 
00300     LONG QueryValue(BYTE* Buf, DWORD* BufSize, LPCTSTR lpszValueName = NULL)
00301     {
00302         DWORD dwType;
00303         LONG lRet = RegQueryValueEx(m_hKey, lpszValueName, NULL,
00304             &dwType, Buf, BufSize);
00305         if (lRet == ERROR_SUCCESS && dwType != REG_BINARY)
00306             return ERROR_INVALID_DATATYPE;
00307         return lRet;
00308     }
00309 
00316     template <class T>
00317     LONG QueryValue(T* buf, int nBuf, LPCTSTR lpszValueName = NULL)
00318     {
00319         DWORD BufSize = sizeof(T)*nBuf, dwType;
00320         LONG lRet = RegQueryString(lpszValueName, &dwType, buf, &BufSize);
00321         if (lRet == ERROR_SUCCESS && !IsStringType(dwType))
00322             return ERROR_INVALID_DATATYPE;
00323         return lRet;
00324     }
00325 
00331     LONG QueryValue(DWORD& dwValue, LPCWSTR lpszValueName = NULL)
00332     {
00333         DWORD dwType, BufSize=sizeof(DWORD);
00334         LONG lRet = RegQueryValueExW(m_hKey, lpszValueName, NULL, &dwType, (LPBYTE)&dwValue, &BufSize);
00335         if (lRet == ERROR_SUCCESS && !IsDWORDType(dwType))
00336             return ERROR_INVALID_DATATYPE;
00337         return lRet;
00338     }
00339 
00345     LONG QueryValue(DWORD& dwValue, LPCSTR lpszValueName = NULL)
00346     {
00347         DWORD dwType, BufSize=sizeof(DWORD);
00348         LONG lRet = RegQueryValueExA(m_hKey, lpszValueName, NULL, &dwType, (LPBYTE)&dwValue, &BufSize);
00349         if (lRet == ERROR_SUCCESS && !IsDWORDType(dwType))
00350             return ERROR_INVALID_DATATYPE;
00351         return lRet;
00352     }
00353 
00364     LONG Create(HKEY hKeyParent, LPCTSTR lpszKeyName, LPTSTR lpszClass = REG_NONE, 
00365                 DWORD dwOptions = REG_OPTION_NON_VOLATILE, REGSAM samDesired = KEY_ALL_ACCESS, 
00366                 LPSECURITY_ATTRIBUTES lpSecAttr = NULL, LPDWORD lpdwDisposition = NULL )
00367     {
00368         Close();
00369         return RegCreateKeyEx(hKeyParent, lpszKeyName, 0, lpszClass, dwOptions,
00370                               samDesired, lpSecAttr, &m_hKey, lpdwDisposition);
00371     }
00372 
00377     LONG DeleteValue(LPCTSTR lpszValueName = NULL)
00378     {
00379         return RegDeleteValue(m_hKey, lpszValueName);
00380     }
00381 
00386     LONG DeleteKey(LPCTSTR lpSubKey = NULL)
00387     {
00388         return RegDeleteKey(m_hKey, lpSubKey);
00389     }
00390 
00396     LONG SetValue(LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL)
00397     {
00398         DWORD DataSize = (DWORD)(_tcslen(lpszValue)+1)*sizeof(TCHAR);
00399         return RegSetValueEx(m_hKey, lpszValueName, 0, REG_SZ, (CONST BYTE*)lpszValue, DataSize);
00400     }
00401 
00409     LONG SetValue(const BYTE* pData, LONG bufSize, DWORD dwType = REG_BINARY, LPCTSTR lpszValueName = NULL)
00410     {
00411         return RegSetValueEx(m_hKey, lpszValueName, 0, dwType, pData, bufSize);
00412     }
00413 
00420     LONG SetValue(DWORD dwValue, LPCTSTR lpszValueName = NULL)
00421     {
00422         return RegSetValueEx(m_hKey, lpszValueName, 0, REG_DWORD, (CONST BYTE*)&dwValue, sizeof(DWORD));
00423     }
00424 
00428     LONG Flush()
00429     {
00430         return RegFlushKey(m_hKey);
00431     }
00432 
00434     operator HKEY() { return m_hKey; }
00435 };
00436 
00437 } // namespace OW32
00438 
00439 #endif // OW32_RegKey_h

Generated on Sun Jun 5 01:29:18 2005 for OW32 by  doxygen 1.3.9.1