/*
* Copyright Likewise Software 2004-2009
* 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:
*
* export.c
*
* Abstract:
*
* Registry
*
* Registry utility functions for regshell
*
* Authors: Wei Fu (wfu@likewise.com)
* Adam Bernstein (abernstein@likewise.com)
*
*/
#include "rsutils.h"
DWORD
RegShellCanonicalizePath(
PSTR pszInDefaultKey,
PSTR pszInKeyName,
PSTR *ppszFullPath,
PSTR *ppszParentPath,
PSTR *ppszSubKey)
{
DWORD dwError = 0;
DWORD dwFullPathLen = 0;
PSTR pszNewPath = NULL;
PSTR pszToken = NULL;
PSTR pszStrtokState = NULL;
PSTR pszTmp = NULL;
PSTR pszStrtokValue = NULL;
/*
* Path is already fully qualified, so just return KeyName as the full path
*/
if (pszInKeyName && (pszInKeyName[0] == '\\'))
{
dwError = RegCStringDuplicate(&pszNewPath, pszInKeyName);
BAIL_ON_REG_ERROR(dwError);
}
else if (pszInKeyName || pszInDefaultKey)
{
if (pszInDefaultKey)
{
dwFullPathLen += strlen(pszInDefaultKey);
}
if (pszInKeyName)
{
dwFullPathLen += strlen(pszInKeyName);
}
/* Leading and separating \ and \0 characters */
dwFullPathLen += 3;
dwError = RegAllocateMemory(sizeof(*pszNewPath) * dwFullPathLen, (PVOID*)&pszNewPath);
BAIL_ON_REG_ERROR(dwError);
if (pszInDefaultKey)
{
strcat(pszNewPath, "\\");
strcat(pszNewPath, pszInDefaultKey);
}
if (pszInKeyName)
{
/* Copy of pszInKeyName because strtok_r modifies this value */
dwError = RegCStringDuplicate(&pszStrtokValue, pszInKeyName);
BAIL_ON_REG_ERROR(dwError);
pszToken = strtok_r(pszStrtokValue, "\\", &pszStrtokState);
while (pszToken)
{
if (strcmp(pszToken, ".") == 0)
{
/* Do nothing */
}
else if (strcmp(pszToken, "..") == 0)
{
/*
* Subtract one directory off the NewPath being
* constructed
*/
pszTmp = strrchr(pszNewPath, '\\');
if (pszTmp)
{
*pszTmp = '\0';
}
else if (strlen(pszNewPath) > 0)
{
*pszNewPath = '\0';
}
}
else if (strncmp(pszToken, "...", 3) == 0)
{
dwError = LWREG_ERROR_INVALID_CONTEXT;
BAIL_ON_REG_ERROR(dwError);
}
else
{
/*
* Append token to end of newPath
*/
strcat(pszNewPath, "\\");
strcat(pszNewPath, pszToken);
}
pszToken = strtok_r(NULL, "\\/", &pszStrtokState);
}
}
}
else if (!pszInDefaultKey)
{
dwError = RegCStringDuplicate(&pszNewPath, "\\");
BAIL_ON_REG_ERROR(dwError);
}
if (strlen(pszNewPath) == 0)
{
strcpy(pszNewPath, "\\");
}
#ifdef _LW_DEBUG
printf("CanonicalizePath: pszNewPath='%s'\n", pszNewPath);
#endif
if (ppszParentPath)
{
dwError = RegCStringDuplicate(ppszParentPath, pszNewPath);
BAIL_ON_REG_ERROR(dwError);
pszTmp = strrchr(*ppszParentPath, '\\');
if (pszTmp)
{
if (pszTmp == *ppszParentPath)
{
pszTmp[1] = '\0';
}
else
{
pszTmp[0] = '\0';
}
}
}
if (ppszSubKey)
{
pszTmp = strrchr(pszNewPath, '\\');
if (pszTmp)
{
dwError = RegCStringDuplicate(ppszSubKey, pszTmp+1);
BAIL_ON_REG_ERROR(dwError);
}
else
{
dwError = RegCStringDuplicate(ppszSubKey, "");
BAIL_ON_REG_ERROR(dwError);
}
}
if (ppszFullPath)
{
*ppszFullPath = pszNewPath;
pszNewPath = NULL;
}
cleanup:
LWREG_SAFE_FREE_STRING(pszNewPath);
LWREG_SAFE_FREE_MEMORY(pszStrtokValue);
LWREG_SAFE_FREE_STRING(pszNewPath);
return dwError;
error:
goto cleanup;
}
DWORD
RegShellIsValidKey(
HANDLE hReg,
PSTR pszRootKeyName,
PSTR pszKey)
{
DWORD dwError = 0;
HKEY pFullKey = NULL;
HKEY pRootKey = NULL;
PWSTR pSubKey = NULL;
BAIL_ON_INVALID_HANDLE(hReg);
BAIL_ON_INVALID_POINTER(pszKey);
if (!pszRootKeyName)
{
pszRootKeyName = HKEY_THIS_MACHINE;
}
dwError = RegOpenKeyExA(hReg, NULL, pszRootKeyName, 0, KEY_READ, &pRootKey);
BAIL_ON_REG_ERROR(dwError);
dwError = RegWC16StringAllocateFromCString(&pSubKey, pszKey);
BAIL_ON_REG_ERROR(dwError);
dwError = RegOpenKeyExW(
hReg,
pRootKey,
pSubKey,
0,
KEY_READ,
&pFullKey);
BAIL_ON_REG_ERROR(dwError);
cleanup:
LWREG_SAFE_FREE_MEMORY(pSubKey);
if (pFullKey)
{
RegCloseKey(hReg, pFullKey);
}
if (pRootKey)
{
RegCloseKey(hReg, pRootKey);
}
return dwError;
error:
goto cleanup;
}
DWORD
RegShellUtilAddKeySecDesc(
HANDLE hReg,
PSTR pszRootKeyName,
PSTR pszDefaultKey,
PSTR pszKeyName,
BOOLEAN bDoBail,
IN ACCESS_MASK AccessDesired,
IN OPTIONAL PSECURITY_DESCRIPTOR_ABSOLUTE pSecurityDescriptor
)
{
DWORD dwError = 0;
HANDLE hRegLocal = NULL;
HKEY pNextKey = NULL;
HKEY pCurrentKey = NULL; //key that to be performed more operations on
PWSTR pwszSubKey = NULL;
PSTR pszToken = NULL;
PSTR pszStrtokState = NULL;
PSTR pszDelim = "\\";
PSTR pszFullPath = NULL;
PSTR pszSubKey = NULL;
DWORD dwDisposition = 0;
if (!hReg)
{
dwError = RegOpenServer(&hRegLocal);
BAIL_ON_REG_ERROR(dwError);
hReg = hRegLocal;
}
if (!pszRootKeyName)
{
pszRootKeyName = HKEY_THIS_MACHINE;
}
dwError = RegShellCanonicalizePath(pszDefaultKey,
pszKeyName,
&pszFullPath,
NULL,
&pszSubKey);
BAIL_ON_REG_ERROR(dwError);
dwError = RegOpenKeyExA(hReg, NULL, pszRootKeyName, 0, KEY_ALL_ACCESS, &pCurrentKey);
BAIL_ON_REG_ERROR(dwError);
pszToken = strtok_r(pszFullPath, pszDelim, &pszStrtokState);
while (!LW_IS_NULL_OR_EMPTY_STR(pszToken))
{
dwError = RegWC16StringAllocateFromCString(&pwszSubKey, pszToken);
BAIL_ON_REG_ERROR(dwError);
dwError = RegCreateKeyExW(
hReg,
pCurrentKey,
pwszSubKey,
0,
NULL,
0,
AccessDesired,
pSecurityDescriptor,
&pNextKey,
&dwDisposition);
BAIL_ON_REG_ERROR(dwError);
LWREG_SAFE_FREE_MEMORY(pwszSubKey);
if (pCurrentKey)
{
dwError = RegCloseKey(hReg, pCurrentKey);
BAIL_ON_REG_ERROR(dwError);
pCurrentKey = NULL;
}
pCurrentKey = pNextKey;
pNextKey = NULL;
pszToken = strtok_r (NULL, pszDelim, &pszStrtokState);
if (LW_IS_NULL_OR_EMPTY_STR(pszToken) &&
REG_OPENED_EXISTING_KEY == dwDisposition && bDoBail)
{
dwError = LWREG_ERROR_KEYNAME_EXIST;
BAIL_ON_REG_ERROR(dwError);
}
}
cleanup:
RegCloseServer(hRegLocal);
if (pCurrentKey)
{
RegCloseKey(hReg, pCurrentKey);
}
if (pNextKey)
{
RegCloseKey(hReg, pNextKey);
}
LWREG_SAFE_FREE_STRING(pszFullPath);
LWREG_SAFE_FREE_STRING(pszSubKey);
LWREG_SAFE_FREE_MEMORY(pwszSubKey);
return dwError;
error:
goto cleanup;
}
DWORD
RegShellUtilAddKey(
HANDLE hReg,
PSTR pszRootKeyName,
PSTR pszDefaultKey,
PSTR pszKeyName,
BOOLEAN bDoBail
)
{
return RegShellUtilAddKeySecDesc(
hReg,
pszRootKeyName,
pszDefaultKey,
pszKeyName,
bDoBail,
KEY_ALL_ACCESS,
NULL);
}
DWORD
RegShellUtilDeleteKey(
HANDLE hReg,
PSTR pszRootKeyName,
PSTR pszDefaultKey,
PSTR keyName)
{
HANDLE hRegLocal = NULL;
PWSTR pwszSubKey = NULL;
HKEY pCurrentKey = NULL;
HKEY pRootKey = NULL;
DWORD dwError = 0;
PSTR pszFullPath = NULL;
PSTR pszParentPath = NULL;
PSTR pszSubKey = NULL;
if (!hReg)
{
dwError = RegOpenServer(&hRegLocal);
BAIL_ON_REG_ERROR(dwError);
hReg = hRegLocal;
}
if (!pszRootKeyName)
{
pszRootKeyName = HKEY_THIS_MACHINE;
}
dwError = RegShellCanonicalizePath(pszDefaultKey,
keyName,
&pszFullPath,
&pszParentPath,
&pszSubKey);
BAIL_ON_REG_ERROR(dwError);
dwError = RegShellIsValidKey(hReg, pszRootKeyName, pszFullPath+1);
BAIL_ON_REG_ERROR(dwError);
dwError = RegOpenKeyExA(hReg, NULL, pszRootKeyName, 0, KEY_ALL_ACCESS, &pRootKey);
BAIL_ON_REG_ERROR(dwError);
if (pszParentPath && pszParentPath[1])
{
dwError = RegWC16StringAllocateFromCString(
&pwszSubKey,
pszParentPath+1);
BAIL_ON_REG_ERROR(dwError);
dwError = RegOpenKeyExW(
hReg,
pRootKey,
pwszSubKey,
0,
KEY_ALL_ACCESS | DELETE,
&pCurrentKey);
BAIL_ON_REG_ERROR(dwError);
LWREG_SAFE_FREE_MEMORY(pwszSubKey);
}
else
{
pCurrentKey = pRootKey;
pRootKey = NULL;
}
dwError = RegWC16StringAllocateFromCString(&pwszSubKey, pszSubKey);
BAIL_ON_REG_ERROR(dwError);
dwError = RegDeleteKeyW(hReg, pCurrentKey, pwszSubKey);
BAIL_ON_REG_ERROR(dwError);
cleanup:
RegCloseServer(hRegLocal);
if (pCurrentKey)
{
RegCloseKey(hReg, pCurrentKey);
}
if (pRootKey)
{
RegCloseKey(hReg, pRootKey);
}
LWREG_SAFE_FREE_MEMORY(pwszSubKey);
LWREG_SAFE_FREE_STRING(pszFullPath);
LWREG_SAFE_FREE_STRING(pszParentPath);
LWREG_SAFE_FREE_STRING(pszSubKey);
return dwError;
error:
goto cleanup;
}
DWORD
RegShellUtilDeleteTree(
HANDLE hReg,
PSTR pszRootKeyName,
PSTR pszDefaultKey,
PSTR keyName)
{
HANDLE hRegLocal = NULL;
PWSTR pwszSubKey = NULL;
HKEY pCurrentKey = NULL;
HKEY pRootKey = NULL;
DWORD dwError = 0;
PSTR pszFullPath = NULL;
PSTR pszParentPath = NULL;
PSTR pszSubKey = NULL;
if (!hReg)
{
dwError = RegOpenServer(&hRegLocal);
BAIL_ON_REG_ERROR(dwError);
hReg = hRegLocal;
}
if (!pszRootKeyName)
{
pszRootKeyName = HKEY_THIS_MACHINE;
}
dwError = RegShellCanonicalizePath(pszDefaultKey,
keyName,
&pszFullPath,
&pszParentPath,
&pszSubKey);
BAIL_ON_REG_ERROR(dwError);
dwError = RegShellIsValidKey(hReg, pszRootKeyName, pszFullPath+1);
BAIL_ON_REG_ERROR(dwError);
dwError = RegOpenKeyExA(hReg, NULL, pszRootKeyName, 0, KEY_ALL_ACCESS, &pRootKey);
BAIL_ON_REG_ERROR(dwError);
if (pszParentPath && pszParentPath[1])
{
dwError = RegWC16StringAllocateFromCString(&pwszSubKey, pszParentPath+1);
BAIL_ON_REG_ERROR(dwError);
dwError = RegOpenKeyExW(
hReg,
pRootKey,
pwszSubKey,
0,
KEY_ALL_ACCESS | DELETE,
&pCurrentKey);
BAIL_ON_REG_ERROR(dwError);
LWREG_SAFE_FREE_MEMORY(pwszSubKey);
}
else
{
pCurrentKey = pRootKey;
pRootKey = NULL;
}
dwError = RegWC16StringAllocateFromCString(&pwszSubKey, pszSubKey);
BAIL_ON_REG_ERROR(dwError);
dwError = RegDeleteTreeW(hReg, pCurrentKey, pwszSubKey);
BAIL_ON_REG_ERROR(dwError);
cleanup:
RegCloseServer(hRegLocal);
if (pCurrentKey)
{
RegCloseKey(hReg, pCurrentKey);
}
if (pRootKey)
{
RegCloseKey(hReg, pRootKey);
}
LWREG_SAFE_FREE_MEMORY(pwszSubKey);
LWREG_SAFE_FREE_STRING(pszFullPath);
LWREG_SAFE_FREE_STRING(pszParentPath);
LWREG_SAFE_FREE_STRING(pszSubKey);
return dwError;
error:
goto cleanup;
}
DWORD
RegShellUtilGetKeys(
HANDLE hReg,
PSTR pszRootKeyName,
PSTR pszDefaultKey,
PSTR keyName,
LW_WCHAR ***pppRetSubKeys,
PDWORD pdwRetSubKeyCount)
{
HANDLE hRegLocal = NULL;
HKEY pRootKey = NULL;
HKEY pFullKey = NULL;
DWORD dwError = 0;
DWORD dwSubKeyCount = 0;
DWORD dwValuesCount = 0;
DWORD dwMaxSubKeyLen = 0;
DWORD i = 0;
DWORD dwSubKeyLen = MAX_KEY_LENGTH;
LW_WCHAR **subKeys = NULL;
PSTR pszParentPath = NULL;
PWSTR pwszSubKey = NULL;
PSTR pszKeyName = NULL;
if (!hReg)
{
dwError = RegOpenServer(&hRegLocal);
BAIL_ON_REG_ERROR(dwError);
hReg = hRegLocal;
}
if (!pszRootKeyName)
{
return RegEnumRootKeysW(hReg,
pppRetSubKeys,
pdwRetSubKeyCount);
}
dwError = RegShellCanonicalizePath(pszDefaultKey,
keyName,
&pszParentPath,
NULL,
NULL);
BAIL_ON_REG_ERROR(dwError);
dwError = RegOpenKeyExA(hReg, NULL, pszRootKeyName, 0, KEY_READ, &pRootKey);
BAIL_ON_REG_ERROR(dwError);
if (pszParentPath && pszParentPath[1])
{
dwError = RegWC16StringAllocateFromCString(&pwszSubKey, pszParentPath+1);
BAIL_ON_REG_ERROR(dwError);
dwError = RegOpenKeyExW(
hReg,
pRootKey,
pwszSubKey,
0,
KEY_READ,
&pFullKey);
BAIL_ON_REG_ERROR(dwError);
LWREG_SAFE_FREE_MEMORY(pwszSubKey);
}
else
{
pFullKey = pRootKey;
pRootKey = NULL;
}
dwError = RegQueryInfoKeyA(
hReg,
pFullKey,
NULL,
NULL,
NULL,
&dwSubKeyCount,
&dwMaxSubKeyLen,
NULL,
&dwValuesCount,
NULL,
NULL,
NULL,
NULL);
BAIL_ON_REG_ERROR(dwError);
if (!dwSubKeyCount)
{
goto done;
}
dwError = RegAllocateMemory(sizeof(*subKeys) * dwSubKeyCount, (PVOID*)&subKeys);
BAIL_ON_REG_ERROR(dwError);
#ifdef _LW_DEBUG
printf( "\nNumber of subkeys: %d\n", dwSubKeyCount);
#endif
for (i = 0; i < dwSubKeyCount; i++)
{
dwSubKeyLen = dwMaxSubKeyLen+1;
dwError = RegAllocateMemory(sizeof(*pszKeyName) * dwSubKeyLen, (PVOID*)&pszKeyName);
BAIL_ON_REG_ERROR(dwError);
dwError = RegEnumKeyExA((HANDLE)hReg,
pFullKey,
i,
pszKeyName,
&dwSubKeyLen,
NULL,
NULL,
NULL,
NULL);
BAIL_ON_REG_ERROR(dwError);
dwError = RegWC16StringAllocateFromCString(&subKeys[i], pszKeyName);
BAIL_ON_REG_ERROR(dwError);
LWREG_SAFE_FREE_STRING(pszKeyName);
pszKeyName = NULL;
}
done:
*pppRetSubKeys = subKeys;
*pdwRetSubKeyCount = dwSubKeyCount;
cleanup:
RegCloseServer(hRegLocal);
if (pFullKey)
{
RegCloseKey(hReg, pFullKey);
}
if (pRootKey)
{
RegCloseKey(hReg, pRootKey);
}
LWREG_SAFE_FREE_STRING(pszParentPath);
LWREG_SAFE_FREE_STRING(pszKeyName);
return dwError;
error:
for (i = 0; subKeys && i 0)
{
dwError = RegAllocateMemory((dwValueLen+1), (PVOID*)&pBuf);
BAIL_ON_REG_ERROR(dwError);
}
memset(pBuf, 0, dwValueLen);
*ppRetBuf = (PVOID) pBuf;
*pdwRetBufLen = dwValueLen;
cleanup:
return dwError;
error:
LWREG_SAFE_FREE_MEMORY(pBuf);
goto cleanup;
}
DWORD
RegShellUtilGetValue(
HANDLE hReg,
PSTR pszRootKeyName,
PSTR pszDefaultKey,
PSTR pszKeyName,
PSTR pszValueName,
PREG_DATA_TYPE pRegType,
PVOID *ppValue,
PDWORD pdwValueLen)
{
HANDLE hRegLocal = NULL;
DWORD dwError = 0;
DWORD dwValueLen = 0;
PDWORD pdwValue = (PDWORD) ppValue;
DWORD dwIndex = 0;
DWORD dwDataType = 0;
PVOID pRetData = NULL;
PBYTE *ppData = (PBYTE *) ppValue;
PSTR *ppszValue = (PSTR *) ppValue;
PSTR **pppszMultiValue = (PSTR **) ppValue;
PSTR *ppszMultiStrArray = NULL;
HKEY hRootKey = NULL;
HKEY hDefaultKey = NULL;
HKEY hFullKeyName = NULL;
if (!hReg)
{
dwError = RegOpenServer(&hRegLocal);
BAIL_ON_REG_ERROR(dwError);
hReg = hRegLocal;
}
if (!pszRootKeyName)
{
pszRootKeyName = HKEY_THIS_MACHINE;
}
/* Open the root key */
dwError = RegOpenKeyExA(
hReg,
NULL,
pszRootKeyName,
0,
KEY_READ,
&hRootKey);
BAIL_ON_REG_ERROR(dwError);
if (pszDefaultKey && *pszDefaultKey)
{
/* Open the default key */
dwError = RegOpenKeyExA(
hReg,
hRootKey,
pszDefaultKey,
0,
KEY_READ,
&hDefaultKey);
BAIL_ON_REG_ERROR(dwError);
}
else
{
hDefaultKey = hRootKey;
hRootKey = NULL;
}
if (pszKeyName && *pszKeyName)
{
/* Open the sub key */
dwError = RegOpenKeyExA(
hReg,
hDefaultKey,
pszKeyName,
0,
KEY_READ,
&hFullKeyName);
BAIL_ON_REG_ERROR(dwError);
}
else
{
hFullKeyName = hDefaultKey;
hDefaultKey = NULL;
}
/* Get the type for the valueName data */
dwError = RegGetValueA(
hReg,
hFullKeyName,
NULL,
pszValueName,
0,
&dwDataType,
NULL,
NULL);
BAIL_ON_REG_ERROR(dwError);
if (pRegType)
{
*pRegType = dwDataType;
}
dwError = RegShellUtilAllocateMemory(
hReg,
hFullKeyName,
dwDataType,
pszValueName,
&pRetData,
&dwValueLen);
BAIL_ON_REG_ERROR(dwError);
switch (dwDataType)
{
case REG_SZ:
dwError = RegGetValueA(
hReg,
hFullKeyName,
NULL,
pszValueName,
REG_SZ,
NULL,
pRetData,
&dwValueLen);
BAIL_ON_REG_ERROR(dwError);
if (ppszValue)
{
*ppszValue = pRetData;
pRetData = NULL;
}
if (pdwValueLen)
{
*pdwValueLen = dwValueLen;
}
break;
case REG_DWORD:
dwValueLen = sizeof(DWORD);
dwError = RegGetValueA(
hReg,
hFullKeyName,
NULL,
pszValueName,
REG_DWORD,
NULL,
pdwValue,
&dwValueLen);
BAIL_ON_REG_ERROR(dwError);
if (pdwValueLen)
{
*pdwValueLen = dwValueLen;
}
break;
case REG_BINARY:
dwError = RegGetValueA(
hReg,
hFullKeyName,
NULL,
pszValueName,
REG_BINARY,
NULL,
pRetData,
&dwValueLen);
BAIL_ON_REG_ERROR(dwError);
if (ppData)
{
*ppData = pRetData;
pRetData = NULL;
}
if (pdwValueLen)
{
*pdwValueLen = dwValueLen;
}
break;
case REG_MULTI_SZ:
if (!pppszMultiValue)
{
goto cleanup;
}
dwError = RegGetValueA(
hReg,
hFullKeyName,
NULL,
pszValueName,
REG_MULTI_SZ,
NULL,
pRetData,
&dwValueLen);
BAIL_ON_REG_ERROR(dwError);
dwError = RegByteArrayToMultiStrsA(
pRetData,
dwValueLen,
&ppszMultiStrArray);
LWREG_SAFE_FREE_MEMORY(pRetData);
BAIL_ON_REG_ERROR(dwError);
/* Return number of entries in multi-string array, not byte count */
for (dwIndex=0; ppszMultiStrArray[dwIndex]; dwIndex++)
;
*pdwValueLen = dwIndex;
*pppszMultiValue = ppszMultiStrArray;
break;
}
cleanup:
LWREG_SAFE_FREE_MEMORY(pRetData);
RegCloseServer(hRegLocal);
if (hFullKeyName)
{
RegCloseKey(hReg, hFullKeyName);
}
if (hDefaultKey)
{
RegCloseKey(hReg, hDefaultKey);
}
if (hRootKey)
{
RegCloseKey(hReg, hRootKey);
}
return dwError;
error:
goto cleanup;
}
DWORD
RegShellUtilEscapeString(
PSTR pszValue,
PSTR *ppszRetValue,
PDWORD pdwEscapeValueLen)
{
DWORD i = 0;
DWORD dwError = 0;
DWORD dwLen = 0;
DWORD dwEscapeValueLen = 0;
PSTR pszRetValue = NULL;
BAIL_ON_INVALID_POINTER(pszValue);
BAIL_ON_INVALID_POINTER(ppszRetValue);
BAIL_ON_INVALID_POINTER(pdwEscapeValueLen);
/* Count number of \ found in string to escape */
for (i=0; pszValue[i]; i++)
{
if (pszValue[i] == '\\' || pszValue[i] == '\n' ||
pszValue[i] == '\r' || pszValue[i] == '"' ||
pszValue[i] == '\t' || pszValue[i] == '\a' ||
pszValue[i] == '\v' || pszValue[i] == '\f')
{
dwEscapeValueLen++;
}
dwEscapeValueLen++;
}
dwEscapeValueLen++;
dwError = RegAllocateMemory(sizeof(*pszRetValue)* dwEscapeValueLen, (PVOID*)&pszRetValue);
BAIL_ON_REG_ERROR(dwError);
for (i=0; pszValue[i]; i++)
{
if (pszValue[i] == '\n')
{
pszRetValue[dwLen++] = '\\';
pszRetValue[dwLen++] = 'n';
}
if (pszValue[i] == '\r')
{
pszRetValue[dwLen++] = '\\';
pszRetValue[dwLen++] = 'r';
}
else if (pszValue[i] == '"')
{
pszRetValue[dwLen++] = '\\';
pszRetValue[dwLen++] = '"';
}
else if (pszValue[i] == '\t')
{
pszRetValue[dwLen++] = '\\';
pszRetValue[dwLen++] = 't';
}
else if (pszValue[i] == '\a')
{
pszRetValue[dwLen++] = '\\';
pszRetValue[dwLen++] = 'a';
}
else if (pszValue[i] == '\v')
{
pszRetValue[dwLen++] = '\\';
pszRetValue[dwLen++] = 'v';
}
else if (pszValue[i] == '\f')
{
pszRetValue[dwLen++] = '\\';
pszRetValue[dwLen++] = 'f';
}
else if (pszValue[i] == '\\')
{
pszRetValue[dwLen++] = '\\';
pszRetValue[dwLen++] = '\\';
}
else
{
pszRetValue[dwLen++] = pszValue[i];
}
}
pszRetValue[dwLen] = '\0';
*ppszRetValue = pszRetValue;
*pdwEscapeValueLen = dwLen;
cleanup:
return dwError;
error:
goto cleanup;
}