/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries * FILE: Copied from advapi32/reg/reg.c * PURPOSE: Registry functions * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) * Thomas Weidenmueller * UPDATE HISTORY: * Created 01/11/98 * 19990309 EA Stubs * 20050502 Fireball imported some stuff from WINE */ #include #define WIN32_NO_STATUS #define _INC_WINDOWS #define COM_NO_WINDOWS_H #include #include #include #include #define NTOS_MODE_USER #include #include #include WINE_DEFAULT_DEBUG_CHANNEL(shell); /****************************************************************************** * load_string [Internal] * * This is basically a copy of user32/resource.c's LoadStringW. Necessary to * avoid importing user32, which is higher level than advapi32. Helper for * RegLoadMUIString. */ 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 = 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; } /************************************************************************ * RegLoadMUIStringW * * @implemented */ LONG WINAPI RegLoadMUIStringW(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) { FIXME("BaseDir parameter not yet supported!\n"); 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 = 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 = HeapAlloc(GetProcessHeap(), 0, cbData); if (!pwszExpandedBuffer) { result = ERROR_NOT_ENOUGH_MEMORY; goto cleanup; } ExpandEnvironmentStringsW(pwszTempBuffer, pwszExpandedBuffer, cbData); } else { pwszExpandedBuffer = 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; } /************************************************************************ * RegLoadMUIStringA * * @implemented */ LONG WINAPI RegLoadMUIStringA(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 = HeapAlloc(GetProcessHeap(), 0, cbData))) { result = ERROR_NOT_ENOUGH_MEMORY; goto cleanup; } result = RegLoadMUIStringW(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); RtlFreeUnicodeString(&baseDirW); RtlFreeUnicodeString(&valueW); return result; }