2025-11-28 00:35:46 +09:00

210 lines
4.0 KiB
C

/* Copyright (c) Microsoft Corporation. All rights reserved. */
#include "windows.h"
#include "wchar.h"
#include "multisz.h"
#include "radutil.h"
static wchar_t wszEmptyMultiSz[] = L"\0";
VOID
WINAPI
MultiSzInit(
PMULTI_SZ pMultiSz
)
{
pMultiSz->pwszValue = wszEmptyMultiSz;
pMultiSz->nChar = 1;
}
VOID
WINAPI
MultiSzFree(
PMULTI_SZ pMultiSz
)
{
if (pMultiSz->pwszValue != wszEmptyMultiSz)
{
RadiusFree(pMultiSz->pwszValue);
}
memset(pMultiSz, 0, sizeof(MULTI_SZ));
}
LONG
WINAPI
MultiSzAppend(
PMULTI_SZ pMultiSz,
LPCWSTR pwszString
)
{
DWORD nChar;
MULTI_SZ result;
PWSTR pwszPos;
/* Calculate the number of characters being added. */
nChar = lstrlenW(pwszString) + 1;
/* Allocate a new MULTI_SZ with enough room for the additional string. */
result.nChar = pMultiSz->nChar + nChar;
result.pwszValue = RadiusAlloc(result.nChar * sizeof(WCHAR));
if (result.pwszValue == NULL)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
/* Copy in the current MULTI_SZ. */
memcpy(
result.pwszValue,
pMultiSz->pwszValue,
(pMultiSz->nChar * sizeof(WCHAR))
);
/* Compute the position to add the new string. */
pwszPos = result.pwszValue + pMultiSz->nChar - 1;
/* Append the string and the extra null-terminator. */
memcpy(
pwszPos,
pwszString,
(nChar * sizeof(WCHAR))
);
pwszPos[nChar] = L'\0';
/* Clean-up the old MULTI_SZ and swap in the new one. */
MultiSzFree(pMultiSz);
*pMultiSz = result;
return NO_ERROR;
}
VOID
WINAPI
MultiSzErase(
PMULTI_SZ pMultiSz,
LPWSTR pwszString
)
{
DWORD nChar;
PWSTR pwszNext, pwszFirst, pwszLast;
/* Compute the number of characters being erased. */
nChar = lstrlenW(pwszString) + 1;
/* Slide everything left to erase the string. */
pwszFirst = pwszString + nChar;
pwszLast = pMultiSz->pwszValue + pMultiSz->nChar;
for (pwszNext = pwszFirst; pwszNext < pwszLast; ++pwszNext)
{
*pwszString++ = *pwszNext;
}
/* Update the length of the MULTI_SZ. */
pMultiSz->nChar -= nChar;
}
LPWSTR
WINAPI
MultiSzFind(
PMULTI_SZ pMultiSz,
LPCWSTR pwszString
)
{
LPWSTR pwszNext;
for (pwszNext = pMultiSz->pwszValue;
*pwszNext != L'\0';
pwszNext += (lstrlenW(pwszNext) + 1))
{
if (lstrcmpiW(pwszNext, pwszString) == 0)
{
return pwszNext;
}
}
return NULL;
}
LONG
WINAPI
MultiSzQuery(
PMULTI_SZ pMultiSz,
HKEY hKey,
LPCWSTR pwszValueName
)
{
LONG lResult;
DWORD dwType, cbData;
LPBYTE lpData;
/* Initialize the MULTI_SZ. */
MultiSzInit(pMultiSz);
/* Compute the size of the value. */
cbData = 0;
lResult = RegQueryValueExW(
hKey,
pwszValueName,
NULL,
&dwType,
NULL,
&cbData
);
if (lResult != NO_ERROR)
{
return lResult;
}
if (dwType != REG_MULTI_SZ)
{
return ERROR_INVALID_DATA;
}
/* Allocate a buffer to hold the MULTI_SZ. */
lpData = RadiusAlloc(cbData);
/* Get the value. */
lResult = RegQueryValueExW(
hKey,
pwszValueName,
NULL,
&dwType,
lpData,
&cbData
);
if (lResult != NO_ERROR)
{
RadiusFree(lpData);
return lResult;
}
if (dwType != REG_MULTI_SZ)
{
RadiusFree(lpData);
return ERROR_INVALID_DATA;
}
/* Store the result. */
pMultiSz->pwszValue = (LPWSTR)lpData;
pMultiSz->nChar = cbData / sizeof(WCHAR);
return NO_ERROR;
}
/* Write a MULTI_SZ to the registry. */
LONG
WINAPI
MultiSzSet(
PMULTI_SZ pMultiSz,
HKEY hKey,
LPCWSTR pwszValueName
)
{
return RegSetValueExW(
hKey,
pwszValueName,
0,
REG_MULTI_SZ,
(const BYTE *)pMultiSz->pwszValue,
pMultiSz->nChar * sizeof(WCHAR)
);
}