1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS system libraries 4 * FILE: Copied from advapi32/reg/reg.c 5 * PURPOSE: Registry functions 6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) 7 * Thomas Weidenmueller <w3seek@reactos.com> 8 * UPDATE HISTORY: 9 * Created 01/11/98 10 * 19990309 EA Stubs 11 * 20050502 Fireball imported some stuff from WINE 12 */ 13 14 #include <stdarg.h> 15 16 #define WIN32_NO_STATUS 17 #define _INC_WINDOWS 18 #define COM_NO_WINDOWS_H 19 20 #include <windef.h> 21 #include <winbase.h> 22 #include <winreg.h> 23 #include <winuser.h> 24 #define NTOS_MODE_USER 25 #include <ndk/rtlfuncs.h> 26 27 #include <wine/debug.h> 28 #include <wine/unicode.h> 29 30 WINE_DEFAULT_DEBUG_CHANNEL(shell); 31 32 /****************************************************************************** 33 * load_string [Internal] 34 * 35 * This is basically a copy of user32/resource.c's LoadStringW. Necessary to 36 * avoid importing user32, which is higher level than advapi32. Helper for 37 * RegLoadMUIString. 38 */ 39 static int load_string(HINSTANCE hModule, UINT resId, LPWSTR pwszBuffer, INT cMaxChars) 40 { 41 HGLOBAL hMemory; 42 HRSRC hResource; 43 WCHAR *pString; 44 int idxString; 45 46 /* Negative values have to be inverted. */ 47 if (HIWORD(resId) == 0xffff) 48 resId = (UINT)(-((INT)resId)); 49 50 /* Load the resource into memory and get a pointer to it. */ 51 hResource = FindResourceW(hModule, MAKEINTRESOURCEW(LOWORD(resId >> 4) + 1), (LPWSTR)RT_STRING); 52 if (!hResource) return 0; 53 hMemory = LoadResource(hModule, hResource); 54 if (!hMemory) return 0; 55 pString = LockResource(hMemory); 56 57 /* Strings are length-prefixed. Lowest nibble of resId is an index. */ 58 idxString = resId & 0xf; 59 while (idxString--) pString += *pString + 1; 60 61 /* If no buffer is given, return length of the string. */ 62 if (!pwszBuffer) return *pString; 63 64 /* Else copy over the string, respecting the buffer size. */ 65 cMaxChars = (*pString < cMaxChars) ? *pString : (cMaxChars - 1); 66 if (cMaxChars >= 0) 67 { 68 memcpy(pwszBuffer, pString+1, cMaxChars * sizeof(WCHAR)); 69 pwszBuffer[cMaxChars] = L'\0'; 70 } 71 72 return cMaxChars; 73 } 74 75 /************************************************************************ 76 * RegLoadMUIStringW 77 * 78 * @implemented 79 */ 80 LONG WINAPI 81 RegLoadMUIStringW(IN HKEY hKey, 82 IN LPCWSTR pszValue OPTIONAL, 83 OUT LPWSTR pszOutBuf, 84 IN DWORD cbOutBuf, 85 OUT LPDWORD pcbData OPTIONAL, 86 IN DWORD Flags, 87 IN LPCWSTR pszDirectory OPTIONAL) 88 { 89 DWORD dwValueType, cbData; 90 LPWSTR pwszTempBuffer = NULL, pwszExpandedBuffer = NULL; 91 LONG result; 92 93 /* Parameter sanity checks. */ 94 if (!hKey || !pszOutBuf) 95 return ERROR_INVALID_PARAMETER; 96 97 if (pszDirectory && *pszDirectory) 98 { 99 FIXME("BaseDir parameter not yet supported!\n"); 100 return ERROR_INVALID_PARAMETER; 101 } 102 103 /* Check for value existence and correctness of it's type, allocate a buffer and load it. */ 104 result = RegQueryValueExW(hKey, pszValue, NULL, &dwValueType, NULL, &cbData); 105 if (result != ERROR_SUCCESS) goto cleanup; 106 if (!(dwValueType == REG_SZ || dwValueType == REG_EXPAND_SZ) || !cbData) 107 { 108 result = ERROR_FILE_NOT_FOUND; 109 goto cleanup; 110 } 111 pwszTempBuffer = HeapAlloc(GetProcessHeap(), 0, cbData); 112 if (!pwszTempBuffer) 113 { 114 result = ERROR_NOT_ENOUGH_MEMORY; 115 goto cleanup; 116 } 117 result = RegQueryValueExW(hKey, pszValue, NULL, &dwValueType, (LPBYTE)pwszTempBuffer, &cbData); 118 if (result != ERROR_SUCCESS) goto cleanup; 119 120 /* Expand environment variables, if appropriate, or copy the original string over. */ 121 if (dwValueType == REG_EXPAND_SZ) 122 { 123 cbData = ExpandEnvironmentStringsW(pwszTempBuffer, NULL, 0) * sizeof(WCHAR); 124 if (!cbData) goto cleanup; 125 pwszExpandedBuffer = HeapAlloc(GetProcessHeap(), 0, cbData); 126 if (!pwszExpandedBuffer) 127 { 128 result = ERROR_NOT_ENOUGH_MEMORY; 129 goto cleanup; 130 } 131 ExpandEnvironmentStringsW(pwszTempBuffer, pwszExpandedBuffer, cbData); 132 } 133 else 134 { 135 pwszExpandedBuffer = HeapAlloc(GetProcessHeap(), 0, cbData); 136 memcpy(pwszExpandedBuffer, pwszTempBuffer, cbData); 137 } 138 139 /* If the value references a resource based string, parse the value and load the string. 140 * Else just copy over the original value. */ 141 result = ERROR_SUCCESS; 142 if (*pwszExpandedBuffer != L'@') /* '@' is the prefix for resource based string entries. */ 143 { 144 lstrcpynW(pszOutBuf, pwszExpandedBuffer, cbOutBuf / sizeof(WCHAR)); 145 } 146 else 147 { 148 WCHAR *pComma = wcsrchr(pwszExpandedBuffer, L','); 149 UINT uiStringId; 150 HMODULE hModule; 151 152 /* Format of the expanded value is 'path_to_dll,-resId' */ 153 if (!pComma || pComma[1] != L'-') 154 { 155 result = ERROR_BADKEY; 156 goto cleanup; 157 } 158 159 uiStringId = _wtoi(pComma+2); 160 *pComma = L'\0'; 161 162 hModule = LoadLibraryExW(pwszExpandedBuffer + 1, NULL, LOAD_LIBRARY_AS_DATAFILE); 163 if (!hModule || !load_string(hModule, uiStringId, pszOutBuf, cbOutBuf / sizeof(WCHAR))) 164 result = ERROR_BADKEY; 165 FreeLibrary(hModule); 166 } 167 168 cleanup: 169 HeapFree(GetProcessHeap(), 0, pwszTempBuffer); 170 HeapFree(GetProcessHeap(), 0, pwszExpandedBuffer); 171 return result; 172 } 173 174 /************************************************************************ 175 * RegLoadMUIStringA 176 * 177 * @implemented 178 */ 179 LONG WINAPI 180 RegLoadMUIStringA(IN HKEY hKey, 181 IN LPCSTR pszValue OPTIONAL, 182 OUT LPSTR pszOutBuf, 183 IN DWORD cbOutBuf, 184 OUT LPDWORD pcbData OPTIONAL, 185 IN DWORD Flags, 186 IN LPCSTR pszDirectory OPTIONAL) 187 { 188 UNICODE_STRING valueW, baseDirW; 189 WCHAR *pwszBuffer; 190 DWORD cbData = cbOutBuf * sizeof(WCHAR); 191 LONG result; 192 193 valueW.Buffer = baseDirW.Buffer = pwszBuffer = NULL; 194 if (!RtlCreateUnicodeStringFromAsciiz(&valueW, pszValue) || 195 !RtlCreateUnicodeStringFromAsciiz(&baseDirW, pszDirectory) || 196 !(pwszBuffer = HeapAlloc(GetProcessHeap(), 0, cbData))) 197 { 198 result = ERROR_NOT_ENOUGH_MEMORY; 199 goto cleanup; 200 } 201 202 result = RegLoadMUIStringW(hKey, valueW.Buffer, pwszBuffer, cbData, NULL, Flags, 203 baseDirW.Buffer); 204 205 if (result == ERROR_SUCCESS) 206 { 207 cbData = WideCharToMultiByte(CP_ACP, 0, pwszBuffer, -1, pszOutBuf, cbOutBuf, NULL, NULL); 208 if (pcbData) 209 *pcbData = cbData; 210 } 211 212 cleanup: 213 HeapFree(GetProcessHeap(), 0, pwszBuffer); 214 RtlFreeUnicodeString(&baseDirW); 215 RtlFreeUnicodeString(&valueW); 216 217 return result; 218 } 219