mirror of
https://github.com/reactos/reactos.git
synced 2024-10-23 06:16:04 +00:00
ef6fc48a38
- Rename the cpp based directory svn path=/branches/shell32_new-bringup/; revision=51895
337 lines
10 KiB
C++
337 lines
10 KiB
C++
|
|
LONG WINAPI RegCopyTreeX(HKEY, LPCWSTR, HKEY)
|
|
{
|
|
DebugBreak();
|
|
return 0;
|
|
}
|
|
|
|
static int load_string(HINSTANCE hModule, UINT resId, LPWSTR pwszBuffer, INT cMaxChars)
|
|
{
|
|
HGLOBAL hMemory;
|
|
HRSRC hResource;
|
|
WCHAR *pString;
|
|
int idxString;
|
|
|
|
/* Negative values have to be inverted. */
|
|
if (HIWORD(resId) == 0xffff)
|
|
resId = (UINT)(-((INT)resId));
|
|
|
|
/* Load the resource into memory and get a pointer to it. */
|
|
hResource = FindResourceW(hModule, MAKEINTRESOURCEW(LOWORD(resId >> 4) + 1), (LPWSTR)RT_STRING);
|
|
if (!hResource) return 0;
|
|
hMemory = LoadResource(hModule, hResource);
|
|
if (!hMemory) return 0;
|
|
pString = (WCHAR *)LockResource(hMemory);
|
|
|
|
/* Strings are length-prefixed. Lowest nibble of resId is an index. */
|
|
idxString = resId & 0xf;
|
|
while (idxString--) pString += *pString + 1;
|
|
|
|
/* If no buffer is given, return length of the string. */
|
|
if (!pwszBuffer) return *pString;
|
|
|
|
/* Else copy over the string, respecting the buffer size. */
|
|
cMaxChars = (*pString < cMaxChars) ? *pString : (cMaxChars - 1);
|
|
if (cMaxChars >= 0)
|
|
{
|
|
memcpy(pwszBuffer, pString+1, cMaxChars * sizeof(WCHAR));
|
|
pwszBuffer[cMaxChars] = L'\0';
|
|
}
|
|
|
|
return cMaxChars;
|
|
}
|
|
|
|
LONG WINAPI
|
|
RegLoadMUIStringWX(IN HKEY hKey,
|
|
IN LPCWSTR pszValue OPTIONAL,
|
|
OUT LPWSTR pszOutBuf,
|
|
IN DWORD cbOutBuf,
|
|
OUT LPDWORD pcbData OPTIONAL,
|
|
IN DWORD Flags,
|
|
IN LPCWSTR pszDirectory OPTIONAL)
|
|
{
|
|
DWORD dwValueType, cbData;
|
|
LPWSTR pwszTempBuffer = NULL, pwszExpandedBuffer = NULL;
|
|
LONG result;
|
|
|
|
/* Parameter sanity checks. */
|
|
if (!hKey || !pszOutBuf)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
if (pszDirectory && *pszDirectory)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* Check for value existence and correctness of it's type, allocate a buffer and load it. */
|
|
result = RegQueryValueExW(hKey, pszValue, NULL, &dwValueType, NULL, &cbData);
|
|
if (result != ERROR_SUCCESS) goto cleanup;
|
|
if (!(dwValueType == REG_SZ || dwValueType == REG_EXPAND_SZ) || !cbData)
|
|
{
|
|
result = ERROR_FILE_NOT_FOUND;
|
|
goto cleanup;
|
|
}
|
|
pwszTempBuffer = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, cbData);
|
|
if (!pwszTempBuffer)
|
|
{
|
|
result = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
result = RegQueryValueExW(hKey, pszValue, NULL, &dwValueType, (LPBYTE)pwszTempBuffer, &cbData);
|
|
if (result != ERROR_SUCCESS) goto cleanup;
|
|
|
|
/* Expand environment variables, if appropriate, or copy the original string over. */
|
|
if (dwValueType == REG_EXPAND_SZ)
|
|
{
|
|
cbData = ExpandEnvironmentStringsW(pwszTempBuffer, NULL, 0) * sizeof(WCHAR);
|
|
if (!cbData) goto cleanup;
|
|
pwszExpandedBuffer = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, cbData);
|
|
if (!pwszExpandedBuffer)
|
|
{
|
|
result = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
ExpandEnvironmentStringsW(pwszTempBuffer, pwszExpandedBuffer, cbData);
|
|
}
|
|
else
|
|
{
|
|
pwszExpandedBuffer = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, cbData);
|
|
memcpy(pwszExpandedBuffer, pwszTempBuffer, cbData);
|
|
}
|
|
|
|
/* If the value references a resource based string, parse the value and load the string.
|
|
* Else just copy over the original value. */
|
|
result = ERROR_SUCCESS;
|
|
if (*pwszExpandedBuffer != L'@') /* '@' is the prefix for resource based string entries. */
|
|
{
|
|
lstrcpynW(pszOutBuf, pwszExpandedBuffer, cbOutBuf / sizeof(WCHAR));
|
|
}
|
|
else
|
|
{
|
|
WCHAR *pComma = wcsrchr(pwszExpandedBuffer, L',');
|
|
UINT uiStringId;
|
|
HMODULE hModule;
|
|
|
|
/* Format of the expanded value is 'path_to_dll,-resId' */
|
|
if (!pComma || pComma[1] != L'-')
|
|
{
|
|
result = ERROR_BADKEY;
|
|
goto cleanup;
|
|
}
|
|
|
|
uiStringId = _wtoi(pComma+2);
|
|
*pComma = L'\0';
|
|
|
|
hModule = LoadLibraryExW(pwszExpandedBuffer + 1, NULL, LOAD_LIBRARY_AS_DATAFILE);
|
|
if (!hModule || !load_string(hModule, uiStringId, pszOutBuf, cbOutBuf / sizeof(WCHAR)))
|
|
result = ERROR_BADKEY;
|
|
FreeLibrary(hModule);
|
|
}
|
|
|
|
cleanup:
|
|
HeapFree(GetProcessHeap(), 0, pwszTempBuffer);
|
|
HeapFree(GetProcessHeap(), 0, pwszExpandedBuffer);
|
|
return result;
|
|
}
|
|
|
|
#if 0
|
|
VOID WINAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString);
|
|
#else
|
|
typedef VOID (WINAPI *PRtlFreeUnicodeString)(PUNICODE_STRING UnicodeString);
|
|
static VOID WINAPI
|
|
RtlFreeUnicodeStringx(PUNICODE_STRING UnicodeString)
|
|
{
|
|
static PRtlFreeUnicodeString Func = NULL;
|
|
|
|
if (Func == NULL)
|
|
{
|
|
HMODULE hShlwapi;
|
|
hShlwapi = LoadLibrary(TEXT("ntdll.DLL"));
|
|
if (hShlwapi != NULL)
|
|
{
|
|
Func = (PRtlFreeUnicodeString)GetProcAddress(hShlwapi, "RtlFreeUnicodeString");
|
|
}
|
|
}
|
|
|
|
if (Func != NULL)
|
|
{
|
|
Func(UnicodeString);
|
|
return;
|
|
}
|
|
|
|
MessageBox(NULL, TEXT("RtlFreeUnicodeString not available"), NULL, 0);
|
|
}
|
|
#endif
|
|
|
|
LONG WINAPI
|
|
RegLoadMUIStringAX(IN HKEY hKey,
|
|
IN LPCSTR pszValue OPTIONAL,
|
|
OUT LPSTR pszOutBuf,
|
|
IN DWORD cbOutBuf,
|
|
OUT LPDWORD pcbData OPTIONAL,
|
|
IN DWORD Flags,
|
|
IN LPCSTR pszDirectory OPTIONAL)
|
|
{
|
|
UNICODE_STRING valueW, baseDirW;
|
|
WCHAR *pwszBuffer;
|
|
DWORD cbData = cbOutBuf * sizeof(WCHAR);
|
|
LONG result;
|
|
|
|
valueW.Buffer = baseDirW.Buffer = pwszBuffer = NULL;
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&valueW, pszValue) ||
|
|
!RtlCreateUnicodeStringFromAsciiz(&baseDirW, pszDirectory) ||
|
|
!(pwszBuffer = (WCHAR *)HeapAlloc(GetProcessHeap(), 0, cbData)))
|
|
{
|
|
result = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
result = RegLoadMUIStringWX(hKey, valueW.Buffer, pwszBuffer, cbData, NULL, Flags,
|
|
baseDirW.Buffer);
|
|
|
|
if (result == ERROR_SUCCESS)
|
|
{
|
|
cbData = WideCharToMultiByte(CP_ACP, 0, pwszBuffer, -1, pszOutBuf, cbOutBuf, NULL, NULL);
|
|
if (pcbData)
|
|
*pcbData = cbData;
|
|
}
|
|
|
|
cleanup:
|
|
HeapFree(GetProcessHeap(), 0, pwszBuffer);
|
|
RtlFreeUnicodeStringx(&baseDirW);
|
|
RtlFreeUnicodeStringx(&valueW);
|
|
|
|
return result;
|
|
}
|
|
|
|
static VOID
|
|
RegpApplyRestrictions(DWORD dwFlags,
|
|
DWORD dwType,
|
|
DWORD cbData,
|
|
PLONG ret)
|
|
{
|
|
/* Check if the type is restricted by the passed flags */
|
|
if (*ret == ERROR_SUCCESS || *ret == ERROR_MORE_DATA)
|
|
{
|
|
DWORD dwMask = 0;
|
|
|
|
switch (dwType)
|
|
{
|
|
case REG_NONE: dwMask = RRF_RT_REG_NONE; break;
|
|
case REG_SZ: dwMask = RRF_RT_REG_SZ; break;
|
|
case REG_EXPAND_SZ: dwMask = RRF_RT_REG_EXPAND_SZ; break;
|
|
case REG_MULTI_SZ: dwMask = RRF_RT_REG_MULTI_SZ; break;
|
|
case REG_BINARY: dwMask = RRF_RT_REG_BINARY; break;
|
|
case REG_DWORD: dwMask = RRF_RT_REG_DWORD; break;
|
|
case REG_QWORD: dwMask = RRF_RT_REG_QWORD; break;
|
|
}
|
|
|
|
if (dwFlags & dwMask)
|
|
{
|
|
/* Type is not restricted, check for size mismatch */
|
|
if (dwType == REG_BINARY)
|
|
{
|
|
DWORD cbExpect = 0;
|
|
|
|
if ((dwFlags & RRF_RT_DWORD) == RRF_RT_DWORD)
|
|
cbExpect = 4;
|
|
else if ((dwFlags & RRF_RT_QWORD) == RRF_RT_QWORD)
|
|
cbExpect = 8;
|
|
|
|
if (cbExpect && cbData != cbExpect)
|
|
*ret = ERROR_DATATYPE_MISMATCH;
|
|
}
|
|
}
|
|
else *ret = ERROR_UNSUPPORTED_TYPE;
|
|
}
|
|
}
|
|
|
|
LONG WINAPI RegGetValueX(HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData)
|
|
{
|
|
DWORD dwType, cbData = pcbData ? *pcbData : 0;
|
|
PVOID pvBuf = NULL;
|
|
LONG ret;
|
|
|
|
if (pvData && !pcbData)
|
|
return ERROR_INVALID_PARAMETER;
|
|
if ((dwFlags & RRF_RT_REG_EXPAND_SZ) && !(dwFlags & RRF_NOEXPAND) &&
|
|
((dwFlags & RRF_RT_ANY) != RRF_RT_ANY))
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
if (pszSubKey && pszSubKey[0])
|
|
{
|
|
ret = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey);
|
|
if (ret != ERROR_SUCCESS) return ret;
|
|
}
|
|
|
|
ret = RegQueryValueExW(hKey, pszValue, NULL, &dwType, (LPBYTE)pvData, &cbData);
|
|
|
|
/* If we are going to expand we need to read in the whole the value even
|
|
* if the passed buffer was too small as the expanded string might be
|
|
* smaller than the unexpanded one and could fit into cbData bytes. */
|
|
if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) &&
|
|
dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND))
|
|
{
|
|
do
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, pvBuf);
|
|
|
|
pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData);
|
|
if (!pvBuf)
|
|
{
|
|
ret = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
if (ret == ERROR_MORE_DATA || !pvData)
|
|
ret = RegQueryValueExW(hKey, pszValue, NULL,
|
|
&dwType, (LPBYTE)pvBuf, &cbData);
|
|
else
|
|
{
|
|
/* Even if cbData was large enough we have to copy the
|
|
* string since ExpandEnvironmentStrings can't handle
|
|
* overlapping buffers. */
|
|
CopyMemory(pvBuf, pvData, cbData);
|
|
}
|
|
|
|
/* Both the type or the value itself could have been modified in
|
|
* between so we have to keep retrying until the buffer is large
|
|
* enough or we no longer have to expand the value. */
|
|
}
|
|
while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA);
|
|
|
|
if (ret == ERROR_SUCCESS)
|
|
{
|
|
/* Recheck dwType in case it changed since the first call */
|
|
if (dwType == REG_EXPAND_SZ)
|
|
{
|
|
cbData = ExpandEnvironmentStringsW((LPCWSTR)pvBuf, (LPWSTR)pvData,
|
|
pcbData ? *pcbData : 0) * sizeof(WCHAR);
|
|
dwType = REG_SZ;
|
|
if (pvData && pcbData && cbData > *pcbData)
|
|
ret = ERROR_MORE_DATA;
|
|
}
|
|
else if (pvData)
|
|
CopyMemory(pvData, pvBuf, *pcbData);
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, pvBuf);
|
|
}
|
|
|
|
if (pszSubKey && pszSubKey[0])
|
|
RegCloseKey(hKey);
|
|
|
|
RegpApplyRestrictions(dwFlags, dwType, cbData, &ret);
|
|
|
|
if (pvData && ret != ERROR_SUCCESS && (dwFlags & RRF_ZEROONFAILURE))
|
|
ZeroMemory(pvData, *pcbData);
|
|
|
|
if (pdwType)
|
|
*pdwType = dwType;
|
|
|
|
if (pcbData)
|
|
*pcbData = cbData;
|
|
|
|
return ret;
|
|
}
|