xref: /reactos/dll/win32/shell32/vista.c (revision 50cf16b3)
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