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