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>
11 * 20050502 Fireball imported some stuff from WINE
14 /* FIXME: This file should go away once we properly handle Vista+ APIs */
18 #define WIN32_NO_STATUS
20 #define COM_NO_WINDOWS_H
26 #define NTOS_MODE_USER
27 #include <ndk/rtlfuncs.h>
29 #include <wine/debug.h>
30 #include <wine/unicode.h>
32 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
34 /******************************************************************************
35 * load_string [Internal]
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
41 static int load_string(HINSTANCE hModule
, UINT resId
, LPWSTR pwszBuffer
, INT cMaxChars
)
48 /* Negative values have to be inverted. */
49 if (HIWORD(resId
) == 0xffff)
50 resId
= (UINT
)(-((INT
)resId
));
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
);
59 /* Strings are length-prefixed. Lowest nibble of resId is an index. */
60 idxString
= resId
& 0xf;
61 while (idxString
--) pString
+= *pString
+ 1;
63 /* If no buffer is given, return length of the string. */
64 if (!pwszBuffer
) return *pString
;
66 /* Else copy over the string, respecting the buffer size. */
67 cMaxChars
= (*pString
< cMaxChars
) ? *pString
: (cMaxChars
- 1);
70 memcpy(pwszBuffer
, pString
+1, cMaxChars
* sizeof(WCHAR
));
71 pwszBuffer
[cMaxChars
] = L
'\0';
77 /************************************************************************
83 RegLoadMUIStringW(IN HKEY hKey
,
84 IN LPCWSTR pszValue OPTIONAL
,
87 OUT LPDWORD pcbData OPTIONAL
,
89 IN LPCWSTR pszDirectory OPTIONAL
)
91 DWORD dwValueType
, cbData
;
92 LPWSTR pwszTempBuffer
= NULL
, pwszExpandedBuffer
= NULL
;
95 /* Parameter sanity checks. */
96 if (!hKey
|| !pszOutBuf
)
97 return ERROR_INVALID_PARAMETER
;
99 if (pszDirectory
&& *pszDirectory
)
101 FIXME("BaseDir parameter not yet supported!\n");
102 return ERROR_INVALID_PARAMETER
;
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
)
110 result
= ERROR_FILE_NOT_FOUND
;
113 pwszTempBuffer
= HeapAlloc(GetProcessHeap(), 0, cbData
);
116 result
= ERROR_NOT_ENOUGH_MEMORY
;
119 result
= RegQueryValueExW(hKey
, pszValue
, NULL
, &dwValueType
, (LPBYTE
)pwszTempBuffer
, &cbData
);
120 if (result
!= ERROR_SUCCESS
) goto cleanup
;
122 /* Expand environment variables, if appropriate, or copy the original string over. */
123 if (dwValueType
== REG_EXPAND_SZ
)
125 cbData
= ExpandEnvironmentStringsW(pwszTempBuffer
, NULL
, 0) * sizeof(WCHAR
);
126 if (!cbData
) goto cleanup
;
127 pwszExpandedBuffer
= HeapAlloc(GetProcessHeap(), 0, cbData
);
128 if (!pwszExpandedBuffer
)
130 result
= ERROR_NOT_ENOUGH_MEMORY
;
133 ExpandEnvironmentStringsW(pwszTempBuffer
, pwszExpandedBuffer
, cbData
);
137 pwszExpandedBuffer
= HeapAlloc(GetProcessHeap(), 0, cbData
);
138 memcpy(pwszExpandedBuffer
, pwszTempBuffer
, cbData
);
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. */
146 lstrcpynW(pszOutBuf
, pwszExpandedBuffer
, cbOutBuf
/ sizeof(WCHAR
));
150 WCHAR
*pComma
= wcsrchr(pwszExpandedBuffer
, L
',');
154 /* Format of the expanded value is 'path_to_dll,-resId' */
155 if (!pComma
|| pComma
[1] != L
'-')
157 result
= ERROR_BADKEY
;
161 uiStringId
= _wtoi(pComma
+2);
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
);
171 HeapFree(GetProcessHeap(), 0, pwszTempBuffer
);
172 HeapFree(GetProcessHeap(), 0, pwszExpandedBuffer
);
176 /************************************************************************
182 RegLoadMUIStringA(IN HKEY hKey
,
183 IN LPCSTR pszValue OPTIONAL
,
186 OUT LPDWORD pcbData OPTIONAL
,
188 IN LPCSTR pszDirectory OPTIONAL
)
190 UNICODE_STRING valueW
, baseDirW
;
192 DWORD cbData
= cbOutBuf
* sizeof(WCHAR
);
195 valueW
.Buffer
= baseDirW
.Buffer
= pwszBuffer
= NULL
;
196 if (!RtlCreateUnicodeStringFromAsciiz(&valueW
, pszValue
) ||
197 !RtlCreateUnicodeStringFromAsciiz(&baseDirW
, pszDirectory
) ||
198 !(pwszBuffer
= HeapAlloc(GetProcessHeap(), 0, cbData
)))
200 result
= ERROR_NOT_ENOUGH_MEMORY
;
204 result
= RegLoadMUIStringW(hKey
, valueW
.Buffer
, pwszBuffer
, cbData
, NULL
, Flags
,
207 if (result
== ERROR_SUCCESS
)
209 cbData
= WideCharToMultiByte(CP_ACP
, 0, pwszBuffer
, -1, pszOutBuf
, cbOutBuf
, NULL
, NULL
);
215 HeapFree(GetProcessHeap(), 0, pwszBuffer
);
216 RtlFreeUnicodeString(&baseDirW
);
217 RtlFreeUnicodeString(&valueW
);