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