/* Editor Settings: expandtabs and use 4 spaces for indentation * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: * * -*- mode: c, c-basic-offset: 4 -*- */ /* * Copyright Likewise Software 2004-2008 * All rights reserved. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the license, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy * of the GNU Lesser General Public License along with this program. If * not, see . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ /* * Copyright (C) Likewise Software. All rights reserved. * * Module Name: * * regutils.h * * Abstract: * * Registry system utilities * * Authors: Krishna Ganugapati (krishnag@likewisesoftware.com) * Sriram Nambakam (snambakam@likewisesoftware.com) * Marc Guy (mguy@likewisesoftware.com) */ #ifndef __REG_UTILS_H__ #define __REG_UTILS_H__ #ifndef WIN32 /* Special check for parsing error codes */ #define BAIL_ON_REG_PARSE_ERROR(dwError) \ if ((dwError != LW_ERROR_SUCCESS) && \ (dwError != REG_ERROR_INSUFFICIENT_BUFFER)) { \ REG_LOG_DEBUG("Error at %s:%d [code: %d]", \ __FILE__, __LINE__, dwError); \ goto error; \ } #ifndef BAIL_ON_NT_STATUS #define BAIL_ON_NT_STATUS(status) \ if ((status) != STATUS_SUCCESS) { \ REG_LOG_DEBUG("Error at %s:%d [status: %s = 0x%08X (%d)]", \ __FILE__, \ __LINE__, \ RegNtStatusToName(status), \ status, status); \ goto error; \ } #endif #define BAIL_ON_REG_ERROR(dwError) \ if (dwError) { \ REG_LOG_DEBUG("Error at %s:%d [code: %d]", __FILE__, __LINE__, dwError); \ goto error; \ } #define BAIL_ON_LWMSG_ERROR(pAssoc, dwError) \ do { \ if (dwError) \ { \ (dwError) = RegTranslateLwMsgError(pAssoc, dwError, __FILE__, __LINE__); \ goto error; \ } \ } while (0) #define BAIL_ON_INVALID_RESERVED_VALUE(dwReserved) \ if (0 != dwReserved) { \ status = STATUS_INVALID_PARAMETER; \ BAIL_ON_NT_STATUS(status); \ } #define BAIL_ON_INVALID_RESERVED_POINTER(pdwReserved) \ if (NULL != pdwReserved) { \ status = STATUS_INVALID_PARAMETER; \ BAIL_ON_NT_STATUS(status); \ } #define BAIL_ON_INVALID_STRING(pszParam) \ if (IsNullOrEmptyString(pszParam)) { \ dwError = ERROR_INVALID_PARAMETER; \ BAIL_ON_REG_ERROR(dwError); \ } #define BAIL_ON_NT_INVALID_STRING(pszParam) \ if (IsNullOrEmptyString(pszParam)) { \ status = STATUS_INVALID_PARAMETER; \ BAIL_ON_NT_STATUS(status); \ } #define BAIL_ON_INVALID_HANDLE(hParam) \ if (hParam == (HANDLE)NULL) { \ dwError = ERROR_INVALID_PARAMETER; \ BAIL_ON_REG_ERROR(dwError); \ } #define BAIL_ON_INVALID_POINTER(p) \ if (NULL == p) { \ dwError = ERROR_INVALID_PARAMETER; \ BAIL_ON_REG_ERROR(dwError); \ } #define BAIL_ON_NT_INVALID_POINTER(p) \ if (NULL == p) { \ status = STATUS_INVALID_PARAMETER; \ BAIL_ON_NT_STATUS(status); \ } #define BAIL_ON_INVALID_KEY_CONTEXT(pKey) \ BAIL_ON_NT_INVALID_POINTER(pKey); \ if (LW_IS_NULL_OR_EMPTY_STR(pKey->pwszKeyName)) \ { \ status = STATUS_INVALID_PARAMETER; \ BAIL_ON_NT_STATUS(status); \ } #define BAIL_ON_INVALID_REG_ENTRY(pRegEntry) \ BAIL_ON_NT_INVALID_POINTER(pRegEntry); \ if (LW_IS_NULL_OR_EMPTY_STR(pRegEntry->pwszKeyName)) \ { \ status = STATUS_INVALID_PARAMETER; \ BAIL_ON_NT_STATUS(status); \ } #define LWREG_SAFE_FREE_MEMORY(mem) \ do { \ if (mem) \ { \ RegMemoryFree(mem); \ (mem) = NULL; \ } \ } while (0) #define LWREG_SAFE_FREE_STRING(str) \ do { \ if (str) \ { \ RegFreeString(str); \ (str) = NULL; \ } \ } while (0) #define LW_IS_NULL_OR_EMPTY_STR(str) (!(str) || !(*(str))) typedef struct __REG_BIT_VECTOR { DWORD dwNumBits; PDWORD pVector; } REG_BIT_VECTOR, *PREG_BIT_VECTOR; typedef struct __REG_HASH_ENTRY REG_HASH_ENTRY; typedef int (*REG_HASH_KEY_COMPARE)(PCVOID, PCVOID); typedef size_t (*REG_HASH_KEY)(PCVOID); typedef void (*REG_HASH_FREE_ENTRY)(const REG_HASH_ENTRY *); typedef DWORD (*REG_HASH_COPY_ENTRY)(const REG_HASH_ENTRY *, REG_HASH_ENTRY *); struct __REG_HASH_ENTRY { PVOID pKey; PVOID pValue; //Next value in chain struct __REG_HASH_ENTRY *pNext; }; typedef struct __REG_HASH_TABLE { size_t sTableSize; size_t sCount; REG_HASH_ENTRY **ppEntries; REG_HASH_KEY_COMPARE fnComparator; REG_HASH_KEY fnHash; REG_HASH_FREE_ENTRY fnFree; REG_HASH_COPY_ENTRY fnCopy; } REG_HASH_TABLE, *PREG_HASH_TABLE; typedef struct __REG_HASH_ITERATOR { REG_HASH_TABLE *pTable; size_t sEntryIndex; REG_HASH_ENTRY *pEntryPos; } REG_HASH_ITERATOR; #define _LW_REG_ASSERT(Expression, Action) \ do { \ if (!(Expression)) \ { \ REG_LOG_DEBUG("Assertion failed: '" # Expression "'"); \ Action; \ } \ } while (0) #define _LW_REG_ASSERT_OR_BAIL(Expression, dwError, Action) \ _LW_REG_ASSERT(Expression, \ (dwError) = ERROR_INTERNAL_ERROR; \ Action ; \ BAIL_ON_REG_ERROR(dwError)) /* * Logging */ #if defined(LW_ENABLE_THREADS) extern pthread_mutex_t gLogLock; #define REG_LOCK_LOGGER pthread_mutex_lock(&gLogLock) #define REG_UNLOCK_LOGGER pthread_mutex_unlock(&gLogLock) #define _REG_LOG_WITH_THREAD(Level, Format, ...) \ _REG_LOG_MESSAGE(Level, \ "0x%lx:" Format, \ (unsigned long)pthread_self(),\ ## __VA_ARGS__) #else #define REG_LOCK_LOGGER #define REG_UNLOCK_LOGGER #define _REG_LOG_WITH_THREAD(Level, Format, ...) \ _REG_LOG_MESSAGE(Level, \ Format, \ ## __VA_ARGS__) #endif #define _REG_LOG_WITH_DEBUG(Level, Format, ...) \ _REG_LOG_WITH_THREAD(Level, \ "[%s() %s:%d] " Format, \ __FUNCTION__, \ __FILE__, \ __LINE__, \ ## __VA_ARGS__) extern HANDLE ghRegLog; extern RegLogLevel gRegMaxLogLevel; extern PFN_REG_LOG_MESSAGE gpfnRegLogger; #define _REG_LOG_MESSAGE(Level, Format, ...) \ RegLogMessage(gpfnRegLogger, ghRegLog, Level, Format, ## __VA_ARGS__) #define _REG_LOG_IF(Level, Format, ...) \ do { \ REG_LOCK_LOGGER; \ if (gpfnRegLogger && (gRegMaxLogLevel >= (Level))) \ { \ if (gRegMaxLogLevel >= REG_LOG_LEVEL_DEBUG) \ { \ _REG_LOG_WITH_DEBUG(Level, Format, ## __VA_ARGS__); \ } \ else \ { \ _REG_LOG_WITH_THREAD(Level, Format, ## __VA_ARGS__); \ } \ } \ REG_UNLOCK_LOGGER; \ } while (0) #define REG_SAFE_LOG_STRING(x) \ ( (x) ? (x) : "" ) #define REG_LOG_ALWAYS(szFmt, ...) \ _REG_LOG_IF(REG_LOG_LEVEL_ALWAYS, szFmt, ## __VA_ARGS__) #define REG_LOG_ERROR(szFmt, ...) \ _REG_LOG_IF(REG_LOG_LEVEL_ERROR, szFmt, ## __VA_ARGS__) #define REG_LOG_WARNING(szFmt, ...) \ _REG_LOG_IF(REG_LOG_LEVEL_WARNING, szFmt, ## __VA_ARGS__) #define REG_LOG_INFO(szFmt, ...) \ _REG_LOG_IF(REG_LOG_LEVEL_INFO, szFmt, ## __VA_ARGS__) #define REG_LOG_VERBOSE(szFmt, ...) \ _REG_LOG_IF(REG_LOG_LEVEL_VERBOSE, szFmt, ## __VA_ARGS__) #define REG_LOG_DEBUG(szFmt, ...) \ _REG_LOG_IF(REG_LOG_LEVEL_DEBUG, szFmt, ## __VA_ARGS__) #if defined(LW_ENABLE_THREADS) extern pthread_mutex_t gTraceLock; #define REG_LOCK_TRACER pthread_mutex_lock(&gTraceLock) #define REG_UNLOCK_TRACER pthread_mutex_unlock(&gTraceLock) #else #define REG_LOCK_TRACER #define REG_UNLOCK_TRACER #endif #define IsNullOrEmptyString(str) (!(str) || !(*(str))) #ifdef NDEBUG #define LW_REG_ASSERT(Expression) #define LW_REG_ASSERT_OR_BAIL(Expression, dwError) \ _LW_REG_ASSERT_OR_BAIL(Expression, dwError, 0) #else #define LW_REG_ASSERT(Expression) \ _LW_REG_ASSERT(Expression, abort()) #define LW_REG_ASSERT_OR_BAIL(Expression, dwError) \ _LW_REG_ASSERT_OR_BAIL(Expression, dwError, abort()) #endif #endif //WIN32 typedef struct __DLINKEDLIST { PVOID pItem; struct __DLINKEDLIST * pNext; struct __DLINKEDLIST * pPrev; } DLINKEDLIST, *PDLINKEDLIST; typedef VOID (*PFN_DLINKEDLIST_FUNC)(PVOID pData, PVOID pUserData); typedef DWORD (*PFN_REG_FOREACH_STACK_ITEM)(PVOID pItem, PVOID pUserData); typedef struct __LWREG_STACK { PVOID pItem; struct __LWREG_STACK * pNext; } LWREG_STACK, *PLWREG_STACK; //defined flags in dwOptions #define REG_CFG_OPTION_STRIP_SECTION 0x00000001 #define REG_CFG_OPTION_STRIP_NAME_VALUE_PAIR 0x00000002 #define REG_CFG_OPTION_STRIP_ALL (REG_CFG_OPTION_STRIP_SECTION | \ REG_CFG_OPTION_STRIP_NAME_VALUE_PAIR) typedef struct _REG_STRING_BUFFER { PSTR pszBuffer; // length of the string excluding terminating null size_t sLen; // capacity of the buffer excluding terminating null size_t sCapacity; } REG_STRING_BUFFER; /* * Config parsing callbacks */ typedef DWORD (*PFNREG_CONFIG_START_SECTION)( PCSTR pszSectionName, PVOID pData, PBOOLEAN pbSkipSection, PBOOLEAN pbContinue ); typedef DWORD (*PFNREG_CONFIG_COMMENT)( PCSTR pszComment, PVOID pData, PBOOLEAN pbContinue ); typedef DWORD (*PFNREG_CONFIG_NAME_VALUE_PAIR)( PCSTR pszName, PCSTR pszValue, PVOID pData, PBOOLEAN pbContinue ); typedef DWORD (*PFNREG_CONFIG_END_SECTION)( PCSTR pszSectionName, PVOID pData, PBOOLEAN pbContinue ); #if !defined(HAVE_STRTOLL) long long int strtoll( const char* nptr, char** endptr, int base ); #endif /* defined(HAVE_STRTOLL) */ #if !defined(HAVE_STRTOULL) unsigned long long int strtoull( const char* nptr, char** endptr, int base ); #endif /* defined(HAVE_STRTOULL) */ DWORD RegRemoveFile( PCSTR pszPath ); DWORD RegCheckFileExists( PCSTR pszPath, PBOOLEAN pbFileExists ); DWORD RegCheckSockExists( PSTR pszPath, PBOOLEAN pbSockExists ); DWORD RegCheckLinkExists( PSTR pszPath, PBOOLEAN pbLinkExists ); DWORD RegCheckFileOrLinkExists( PSTR pszPath, PBOOLEAN pbExists ); DWORD RegMoveFile( PCSTR pszSrcPath, PCSTR pszDstPath ); DWORD RegChangePermissions( PCSTR pszPath, mode_t dwFileMode ); DWORD RegChangeOwner( PCSTR pszPath, uid_t uid, gid_t gid ); DWORD RegChangeDirectory( PSTR pszPath ); DWORD RegRemoveDirectory( PSTR pszPath ); DWORD RegCheckDirectoryExists( PCSTR pszPath, PBOOLEAN pbDirExists ); DWORD RegGetCurrentDirectoryPath( PSTR* ppszPath ); DWORD RegCreateDirectory( PCSTR pszPath, mode_t dwFileMode ); DWORD RegGetDirectoryFromPath( IN PCSTR pszPath, OUT PSTR* ppszDir ); DWORD RegGetOwnerAndPermissions( PCSTR pszSrcPath, uid_t * uid, gid_t * gid, mode_t * mode ); DWORD RegCopyFileWithPerms( PCSTR pszSrcPath, PCSTR pszDstPath, mode_t dwPerms ); DWORD RegCopyFileWithOriginalPerms( PCSTR pszSrcPath, PCSTR pszDstPath ); DWORD RegChangeOwnerAndPermissions( PCSTR pszPath, uid_t uid, gid_t gid, mode_t dwFileMode ); DWORD RegBackupFile( PCSTR pszPath ); DWORD RegGetSymlinkTarget( PCSTR pszPath, PSTR* ppszTargetPath ); DWORD RegCreateSymlink( PCSTR pszOldPath, PCSTR pszNewPath ); DWORD RegCopyDirectory( PCSTR pszSourceDirPath, uid_t ownerUid, gid_t ownerGid, PCSTR pszDestDirPath ); DWORD RegGetMatchingFilePathsInFolder( PCSTR pszDirPath, PCSTR pszFileNameRegExp, PSTR** pppszHostFilePaths, PDWORD pdwNPaths ); DWORD RegInitLogging( PCSTR pszProgramName, RegLogTarget logTarget, RegLogLevel maxAllowedLogLevel, PCSTR pszPath ); DWORD RegLogGetInfo( PREG_LOG_INFO* ppLogInfo ); void reg_vsyslog( int priority, const char *format, va_list ap ); DWORD RegShutdownLogging( VOID ); VOID RegLogMessage( PFN_REG_LOG_MESSAGE pfnLogger, HANDLE hLog, RegLogLevel logLevel, PCSTR pszFormat, ... ); DWORD RegDLinkedList( PDLINKEDLIST* ppList, PVOID pItem ); DWORD RegDLinkedListAppend( PDLINKEDLIST* ppList, PVOID pItem ); DWORD RegDLinkedListPrepend( PDLINKEDLIST* ppList, PVOID pItem ); BOOLEAN RegDLinkedListDelete( PDLINKEDLIST* ppList, PVOID pItem ); VOID RegDLinkedListForEach( PDLINKEDLIST pList, PFN_DLINKEDLIST_FUNC pFunc, PVOID pUserData ); VOID RegDLinkedListFree( PDLINKEDLIST pList ); NTSTATUS RegHashCreate( size_t sTableSize, REG_HASH_KEY_COMPARE fnComparator, REG_HASH_KEY fnHash, REG_HASH_FREE_ENTRY fnFree, //optional REG_HASH_COPY_ENTRY fnCopy, //optional REG_HASH_TABLE** ppResult ); void RegHashRemoveAll( REG_HASH_TABLE* pResult ); void RegHashSafeFree( REG_HASH_TABLE** ppResult ); NTSTATUS RegHashSetValue( REG_HASH_TABLE *pTable, PVOID pKey, PVOID pValue ); //Returns ENOENT if pKey is not in the table NTSTATUS RegHashGetValue( REG_HASH_TABLE *pTable, PCVOID pKey, PVOID* ppValue ); BOOLEAN RegHashExists( IN PREG_HASH_TABLE pTable, IN PCVOID pKey ); NTSTATUS RegHashCopy( IN REG_HASH_TABLE *pTable, OUT REG_HASH_TABLE **ppResult ); //Invalidates all iterators NTSTATUS RegHashResize( REG_HASH_TABLE *pTable, size_t sTableSize ); VOID RegHashGetIterator( REG_HASH_TABLE *pTable, REG_HASH_ITERATOR *pIterator ); // returns NULL after passing the last entry REG_HASH_ENTRY * RegHashNext( REG_HASH_ITERATOR *pIterator ); NTSTATUS RegHashRemoveKey( REG_HASH_TABLE *pTable, PVOID pKey ); int RegHashCaselessWC16StringCompare( PCVOID str1, PCVOID str2 ); size_t RegHashCaselessStringHash( PCVOID str ); size_t RegHashCaselessWc16String( PCVOID str ); int RegHashPVoidCompare( IN PCVOID pvData1, IN PCVOID pvData2 ); size_t RegHashPVoidHash( IN PCVOID pvData ); VOID RegHashFreeWc16StringKey( IN OUT const REG_HASH_ENTRY *pEntry ); NTSTATUS RegInitializeStringBuffer( REG_STRING_BUFFER *pBuffer, size_t sCapacity ); NTSTATUS RegAppendStringBuffer( REG_STRING_BUFFER *pBuffer, PCSTR pszAppend ); void RegFreeStringBufferContents( REG_STRING_BUFFER *pBuffer ); VOID RegPrintError( IN OPTIONAL PCSTR pszErrorPrefix, IN DWORD dwError ); DWORD RegMapErrnoToLwRegError( DWORD dwErrno ); DWORD RegNtStatusToWin32Error( NTSTATUS ntStatus ); PCSTR RegNtStatusToName( IN NTSTATUS status ); DWORD RegReallocMemory( IN PVOID pMemory, OUT PVOID* ppNewMemory, IN DWORD dwSize ); NTSTATUS NtRegReallocMemory( IN PVOID pMemory, OUT PVOID* ppNewMemory, IN DWORD dwSize ); void RegFreeString( PSTR pszString ); void RegFreeStringArray( PSTR * ppStringArray, DWORD dwCount ); void RegFreeWC16StringArray( PWSTR * ppwStringArray, DWORD dwCount ); void RegFreeValueByteArray( PBYTE* ppValues, DWORD dwCount ); DWORD RegStrndup( PCSTR pszInputString, size_t size, PSTR * ppszOutputString ); NTSTATUS RegHexStrToByteArray( IN PCSTR pszHexString, IN OPTIONAL DWORD* pdwHexStringLength, OUT UCHAR** ppucByteArray, OUT DWORD* pdwByteArrayLength ); NTSTATUS RegByteArrayToHexStr( IN UCHAR* pucByteArray, IN DWORD dwByteArrayLength, OUT PSTR* ppszHexString ); NTSTATUS RegStrDupOrNull( PCSTR pszInputString, PSTR *ppszOutputString ); NTSTATUS RegWcStrDupOrNull( PCWSTR pwszInputString, PWSTR *ppwszOutputString ); void RegStripWhitespace( PSTR pszString, BOOLEAN bLeading, BOOLEAN bTrailing ); NTSTATUS RegCopyValueBytes( IN PBYTE pValue, IN DWORD dwValueLen, OUT OPTIONAL PBYTE pData, IN OUT OPTIONAL PDWORD pcbData ); DWORD RegAllocateMemory( size_t Size, LW_PVOID * ppMemory ); DWORD RegCStringDuplicate( OUT PSTR* ppszNewString, IN PCSTR pszOriginalString ); void RegMemoryFree( IN OUT LW_PVOID pMemory ); DWORD RegWC16StringAllocateFromCString( OUT PWSTR* ppszNewString, IN PCSTR pszOriginalString ); DWORD RegCStringAllocateFromWC16String( OUT PSTR* ppszNewString, IN PCWSTR pszOriginalString ); DWORD RegCStringAllocatePrintf( OUT PSTR* ppszString, IN PCSTR pszFormat, IN ... ); PCWSTR RegStrrchr( PCWSTR pwszStr, wchar16_t wch ); PCWSTR RegStrchr( PCWSTR pwszStr, wchar16_t wch ); #endif /* __REG_UTILS_H__ */