Sync with trunk r63174.
[reactos.git] / dll / win32 / advpack / reg.c
1 /*
2 * Advpack registry functions
3 *
4 * Copyright 2004 Huw D M Davies
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "advpack_private.h"
22
23 static const WCHAR REGINST[] = {'R','E','G','I','N','S','T',0};
24 static const WCHAR Strings[] = {'S','t','r','i','n','g','s',0};
25 static const WCHAR MOD_PATH[] = {'_','M','O','D','_','P','A','T','H',0};
26 static const WCHAR SYS_MOD_PATH[] = {'_','S','Y','S','_','M','O','D','_','P','A','T','H',0};
27 static const WCHAR SystemRoot[] = {'S','y','s','t','e','m','R','o','o','t',0};
28 static const WCHAR escaped_SystemRoot[] = {'%','S','y','s','t','e','m','R','o','o','t','%',0};
29 static const WCHAR quote[] = {'\"',0};
30
31 static BOOL get_temp_ini_path(LPWSTR name)
32 {
33 WCHAR tmp_dir[MAX_PATH];
34 WCHAR prefix[] = {'a','v','p',0};
35
36 if(!GetTempPathW(sizeof(tmp_dir)/sizeof(WCHAR), tmp_dir))
37 return FALSE;
38
39 if(!GetTempFileNameW(tmp_dir, prefix, 0, name))
40 return FALSE;
41 return TRUE;
42 }
43
44 static BOOL create_tmp_ini_file(HMODULE hm, WCHAR *ini_file)
45 {
46 HRSRC hrsrc;
47 HGLOBAL hmem = NULL;
48 DWORD rsrc_size, bytes_written;
49 VOID *rsrc_data;
50 HANDLE hf = INVALID_HANDLE_VALUE;
51
52 if(!get_temp_ini_path(ini_file)) {
53 ERR("Can't get temp ini file path\n");
54 goto error;
55 }
56
57 if(!(hrsrc = FindResourceW(hm, REGINST, REGINST))) {
58 ERR("Can't find REGINST resource\n");
59 goto error;
60 }
61
62 rsrc_size = SizeofResource(hm, hrsrc);
63 hmem = LoadResource(hm, hrsrc);
64 rsrc_data = LockResource(hmem);
65
66 if(!rsrc_data || !rsrc_size) {
67 ERR("Can't load REGINST resource\n");
68 goto error;
69 }
70
71 if((hf = CreateFileW(ini_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
72 FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
73 ERR("Unable to create temp ini file\n");
74 goto error;
75 }
76 if(!WriteFile(hf, rsrc_data, rsrc_size, &bytes_written, NULL) || rsrc_size != bytes_written) {
77 ERR("Write failed\n");
78 goto error;
79 }
80 FreeResource(hmem);
81 CloseHandle(hf);
82 return TRUE;
83 error:
84 if(hmem) FreeResource(hmem);
85 if(hf != INVALID_HANDLE_VALUE) CloseHandle(hf);
86 return FALSE;
87 }
88
89 static void strentry_atow(const STRENTRYA *aentry, STRENTRYW *wentry)
90 {
91 DWORD name_len, val_len;
92
93 name_len = MultiByteToWideChar(CP_ACP, 0, aentry->pszName, -1, NULL, 0);
94 val_len = MultiByteToWideChar(CP_ACP, 0, aentry->pszValue, -1, NULL, 0);
95
96 wentry->pszName = HeapAlloc(GetProcessHeap(), 0, name_len * sizeof(WCHAR));
97 wentry->pszValue = HeapAlloc(GetProcessHeap(), 0, val_len * sizeof(WCHAR));
98
99 MultiByteToWideChar(CP_ACP, 0, aentry->pszName, -1, wentry->pszName, name_len);
100 MultiByteToWideChar(CP_ACP, 0, aentry->pszValue, -1, wentry->pszValue, val_len);
101 }
102
103 static STRTABLEW *strtable_atow(const STRTABLEA *atable)
104 {
105 STRTABLEW *wtable;
106 DWORD j;
107
108 wtable = HeapAlloc(GetProcessHeap(), 0, sizeof(STRTABLEW));
109 wtable->pse = HeapAlloc(GetProcessHeap(), 0, atable->cEntries * sizeof(STRENTRYW));
110 wtable->cEntries = atable->cEntries;
111
112 for (j = 0; j < wtable->cEntries; j++)
113 strentry_atow(&atable->pse[j], &wtable->pse[j]);
114
115 return wtable;
116 }
117
118 static void free_strtable(STRTABLEW *wtable)
119 {
120 DWORD j;
121
122 for (j = 0; j < wtable->cEntries; j++)
123 {
124 HeapFree(GetProcessHeap(), 0, wtable->pse[j].pszName);
125 HeapFree(GetProcessHeap(), 0, wtable->pse[j].pszValue);
126 }
127
128 HeapFree(GetProcessHeap(), 0, wtable->pse);
129 HeapFree(GetProcessHeap(), 0, wtable);
130 }
131
132 /***********************************************************************
133 * RegInstallA (advpack.@)
134 *
135 * See RegInstallW.
136 */
137 HRESULT WINAPI RegInstallA(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable)
138 {
139 UNICODE_STRING section;
140 STRTABLEW *wtable;
141 HRESULT hr;
142
143 TRACE("(%p, %s, %p)\n", hm, debugstr_a(pszSection), pstTable);
144
145 if (pstTable)
146 wtable = strtable_atow(pstTable);
147 else
148 wtable = NULL;
149
150 RtlCreateUnicodeStringFromAsciiz(&section, pszSection);
151
152 hr = RegInstallW(hm, section.Buffer, wtable);
153
154 if (pstTable)
155 free_strtable(wtable);
156
157 RtlFreeUnicodeString(&section);
158
159 return hr;
160 }
161
162 static HRESULT write_predefined_strings(HMODULE hm, LPCWSTR ini_path)
163 {
164 WCHAR mod_path[MAX_PATH + 2];
165 WCHAR sys_mod_path[MAX_PATH + 2];
166 WCHAR sys_root[MAX_PATH];
167
168 *mod_path = '\"';
169 if (!GetModuleFileNameW(hm, mod_path + 1, sizeof(mod_path) / sizeof(WCHAR) - 2))
170 return E_FAIL;
171
172 lstrcatW(mod_path, quote);
173 WritePrivateProfileStringW(Strings, MOD_PATH, mod_path, ini_path);
174
175 *sys_root = '\0';
176 GetEnvironmentVariableW(SystemRoot, sys_root, sizeof(sys_root) / sizeof(WCHAR));
177
178 if(!strncmpiW(sys_root, mod_path + 1, strlenW(sys_root)))
179 {
180 *sys_mod_path = '\"';
181 strcpyW(sys_mod_path + 1, escaped_SystemRoot);
182 strcatW(sys_mod_path, mod_path + 1 + strlenW(sys_root));
183 }
184 else
185 {
186 FIXME("SYS_MOD_PATH needs more work\n");
187 strcpyW(sys_mod_path, mod_path);
188 }
189
190 WritePrivateProfileStringW(Strings, SYS_MOD_PATH, sys_mod_path, ini_path);
191
192 return S_OK;
193 }
194
195 /***********************************************************************
196 * RegInstallW (advpack.@)
197 *
198 * Loads an INF from a string resource, adds entries to the string
199 * substitution table, and executes the INF.
200 *
201 * PARAMS
202 * hm [I] Module that contains the REGINST resource.
203 * pszSection [I] The INF section to execute.
204 * pstTable [I] Table of string substitutions.
205 *
206 * RETURNS
207 * Success: S_OK.
208 * Failure: E_FAIL.
209 */
210 HRESULT WINAPI RegInstallW(HMODULE hm, LPCWSTR pszSection, const STRTABLEW* pstTable)
211 {
212 unsigned int i;
213 CABINFOW cabinfo;
214 WCHAR tmp_ini_path[MAX_PATH];
215 HRESULT hr = E_FAIL;
216
217 TRACE("(%p, %s, %p)\n", hm, debugstr_w(pszSection), pstTable);
218
219 if(!create_tmp_ini_file(hm, tmp_ini_path))
220 return E_FAIL;
221
222 if (write_predefined_strings(hm, tmp_ini_path) != S_OK)
223 goto done;
224
225 /* Write the additional string table */
226 if (pstTable)
227 {
228 for(i = 0; i < pstTable->cEntries; i++)
229 {
230 WCHAR tmp_value[MAX_PATH + 2];
231
232 tmp_value[0] = '\"';
233 lstrcpyW(tmp_value + 1, pstTable->pse[i].pszValue);
234 lstrcatW(tmp_value, quote);
235
236 WritePrivateProfileStringW(Strings, pstTable->pse[i].pszName, tmp_value, tmp_ini_path);
237 }
238 }
239
240 /* flush cache */
241 WritePrivateProfileStringW(NULL, NULL, NULL, tmp_ini_path);
242
243 /* FIXME: read AdvOptions val for dwFlags */
244 ZeroMemory(&cabinfo, sizeof(CABINFOW));
245 cabinfo.pszInf = tmp_ini_path;
246 cabinfo.pszSection = (LPWSTR)pszSection;
247 cabinfo.dwFlags = 0;
248
249 hr = ExecuteCabW(NULL, &cabinfo, NULL);
250
251 done:
252
253 DeleteFileW(tmp_ini_path);
254
255 return hr;
256 }
257
258 /***********************************************************************
259 * RegRestoreAllA (advpack.@)
260 *
261 * See RegRestoreAllW.
262 */
263 HRESULT WINAPI RegRestoreAllA(HWND hWnd, LPSTR pszTitleString, HKEY hkBackupKey)
264 {
265 UNICODE_STRING title;
266 HRESULT hr;
267
268 TRACE("(%p, %s, %p)\n", hWnd, debugstr_a(pszTitleString), hkBackupKey);
269
270 RtlCreateUnicodeStringFromAsciiz(&title, pszTitleString);
271
272 hr = RegRestoreAllW(hWnd, title.Buffer, hkBackupKey);
273
274 RtlFreeUnicodeString(&title);
275
276 return hr;
277 }
278
279 /***********************************************************************
280 * RegRestoreAllW (advpack.@)
281 *
282 * Restores all saved registry entries.
283 *
284 * PARAMS
285 * hWnd [I] Handle to the window used for the display.
286 * pszTitleString [I] Title of the window.
287 * hkBackupKey [I] Handle to the backup key.
288 *
289 * RETURNS
290 * Success: S_OK.
291 * Failure: E_FAIL.
292 *
293 * BUGS
294 * Unimplemented.
295 */
296 HRESULT WINAPI RegRestoreAllW(HWND hWnd, LPWSTR pszTitleString, HKEY hkBackupKey)
297 {
298 FIXME("(%p, %s, %p) stub\n", hWnd, debugstr_w(pszTitleString), hkBackupKey);
299
300 return E_FAIL;
301 }
302
303 /***********************************************************************
304 * RegSaveRestoreA (advpack.@)
305 *
306 * See RegSaveRestoreW.
307 */
308 HRESULT WINAPI RegSaveRestoreA(HWND hWnd, LPCSTR pszTitleString, HKEY hkBackupKey,
309 LPCSTR pcszRootKey, LPCSTR pcszSubKey,
310 LPCSTR pcszValueName, DWORD dwFlags)
311 {
312 UNICODE_STRING title, root, subkey, value;
313 HRESULT hr;
314
315 TRACE("(%p, %s, %p, %s, %s, %s, %d)\n", hWnd, debugstr_a(pszTitleString),
316 hkBackupKey, debugstr_a(pcszRootKey), debugstr_a(pcszSubKey),
317 debugstr_a(pcszValueName), dwFlags);
318
319 RtlCreateUnicodeStringFromAsciiz(&title, pszTitleString);
320 RtlCreateUnicodeStringFromAsciiz(&root, pcszRootKey);
321 RtlCreateUnicodeStringFromAsciiz(&subkey, pcszSubKey);
322 RtlCreateUnicodeStringFromAsciiz(&value, pcszValueName);
323
324 hr = RegSaveRestoreW(hWnd, title.Buffer, hkBackupKey, root.Buffer,
325 subkey.Buffer, value.Buffer, dwFlags);
326
327 RtlFreeUnicodeString(&title);
328 RtlFreeUnicodeString(&root);
329 RtlFreeUnicodeString(&subkey);
330 RtlFreeUnicodeString(&value);
331
332 return hr;
333 }
334
335 /***********************************************************************
336 * RegSaveRestoreW (advpack.@)
337 *
338 * Saves or restores the specified registry value.
339 *
340 * PARAMS
341 * hWnd [I] Handle to the window used for the display.
342 * pszTitleString [I] Title of the window.
343 * hkBackupKey [I] Key used to store the backup data.
344 * pcszRootKey [I] Root key of the registry value
345 * pcszSubKey [I] Sub key of the registry value.
346 * pcszValueName [I] Value to save or restore.
347 * dwFlags [I] See advpub.h.
348 *
349 * RETURNS
350 * Success: S_OK.
351 * Failure: E_FAIL.
352 *
353 * BUGS
354 * Unimplemented.
355 */
356 HRESULT WINAPI RegSaveRestoreW(HWND hWnd, LPCWSTR pszTitleString, HKEY hkBackupKey,
357 LPCWSTR pcszRootKey, LPCWSTR pcszSubKey,
358 LPCWSTR pcszValueName, DWORD dwFlags)
359 {
360 FIXME("(%p, %s, %p, %s, %s, %s, %d): stub\n", hWnd, debugstr_w(pszTitleString),
361 hkBackupKey, debugstr_w(pcszRootKey), debugstr_w(pcszSubKey),
362 debugstr_w(pcszValueName), dwFlags);
363
364 return E_FAIL;
365 }
366
367 /***********************************************************************
368 * RegSaveRestoreOnINFA (advpack.@)
369 *
370 * See RegSaveRestoreOnINFW.
371 */
372 HRESULT WINAPI RegSaveRestoreOnINFA(HWND hWnd, LPCSTR pszTitle, LPCSTR pszINF,
373 LPCSTR pszSection, HKEY hHKLMBackKey,
374 HKEY hHKCUBackKey, DWORD dwFlags)
375 {
376 UNICODE_STRING title, inf, section;
377 HRESULT hr;
378
379 TRACE("(%p, %s, %s, %s, %p, %p, %d)\n", hWnd, debugstr_a(pszTitle),
380 debugstr_a(pszINF), debugstr_a(pszSection),
381 hHKLMBackKey, hHKCUBackKey, dwFlags);
382
383 RtlCreateUnicodeStringFromAsciiz(&title, pszTitle);
384 RtlCreateUnicodeStringFromAsciiz(&inf, pszINF);
385 RtlCreateUnicodeStringFromAsciiz(&section, pszSection);
386
387 hr = RegSaveRestoreOnINFW(hWnd, title.Buffer, inf.Buffer, section.Buffer,
388 hHKLMBackKey, hHKCUBackKey, dwFlags);
389
390 RtlFreeUnicodeString(&title);
391 RtlFreeUnicodeString(&inf);
392 RtlFreeUnicodeString(&section);
393
394 return hr;
395 }
396
397 /***********************************************************************
398 * RegSaveRestoreOnINFW (advpack.@)
399 *
400 * Saves or restores the specified INF Reg section.
401 *
402 * PARAMS
403 * hWnd [I] Handle to the window used for the display.
404 * pszTitle [I] Title of the window.
405 * pszINF [I] Filename of the INF.
406 * pszSection [I] Section to save or restore.
407 * hHKLMBackKey [I] Opened key in HKLM to store data.
408 * hHKCUBackKey [I] Opened key in HKCU to store data.
409 * dwFlags [I] See advpub.h
410 *
411 * RETURNS
412 * Success: S_OK.
413 * Failure: E_FAIL.
414 *
415 * BUGS
416 * Unimplemented.
417 */
418 HRESULT WINAPI RegSaveRestoreOnINFW(HWND hWnd, LPCWSTR pszTitle, LPCWSTR pszINF,
419 LPCWSTR pszSection, HKEY hHKLMBackKey,
420 HKEY hHKCUBackKey, DWORD dwFlags)
421 {
422 FIXME("(%p, %s, %s, %s, %p, %p, %d): stub\n", hWnd, debugstr_w(pszTitle),
423 debugstr_w(pszINF), debugstr_w(pszSection),
424 hHKLMBackKey, hHKCUBackKey, dwFlags);
425
426 return E_FAIL;
427 }