/*1* Registry management2*3* Copyright (C) 1999 Alexandre Julliard4* Copyright (C) 2017 Dmitry Timoshkov5*6* Based on misc/registry.c code7* Copyright (C) 1996 Marcus Meissner8* Copyright (C) 1998 Matthew Becker9* Copyright (C) 1999 Sylvain St-Germain10*11* This library is free software; you can redistribute it and/or12* modify it under the terms of the GNU Lesser General Public13* License as published by the Free Software Foundation; either14* version 2.1 of the License, or (at your option) any later version.15*16* This library is distributed in the hope that it will be useful,17* but WITHOUT ANY WARRANTY; without even the implied warranty of18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU19* Lesser General Public License for more details.20*21* You should have received a copy of the GNU Lesser General Public22* License along with this library; if not, write to the Free Software23* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA24*/2526#include <stdlib.h>27#include <stdarg.h>28#include <stdio.h>2930#include "ntstatus.h"31#define WIN32_NO_STATUS32#include "windef.h"33#include "winbase.h"34#include "winreg.h"35#include "winerror.h"36#include "winternl.h"3738#include "wine/debug.h"39#include "wine/list.h"4041WINE_DEFAULT_DEBUG_CHANNEL(reg);4243NTSTATUS WINAPI RemapPredefinedHandleInternal( HKEY hkey, HKEY override );44NTSTATUS WINAPI DisablePredefinedHandleTableInternal( HKEY hkey );454647/******************************************************************************48* RegOverridePredefKey [ADVAPI32.@]49*/50LSTATUS WINAPI RegOverridePredefKey( HKEY hkey, HKEY override )51{52return RtlNtStatusToDosError( RemapPredefinedHandleInternal( hkey, override ));53}545556/******************************************************************************57* RegCreateKeyW [ADVAPI32.@]58*59* Creates the specified reg key.60*61* PARAMS62* hKey [I] Handle to an open key.63* lpSubKey [I] Name of a key that will be opened or created.64* phkResult [O] Receives a handle to the opened or created key.65*66* RETURNS67* Success: ERROR_SUCCESS68* Failure: nonzero error code defined in Winerror.h69*/70LSTATUS WINAPI RegCreateKeyW( HKEY hkey, LPCWSTR lpSubKey, PHKEY phkResult )71{72if (!phkResult)73return ERROR_INVALID_PARAMETER;7475return RegCreateKeyExW( hkey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE,76MAXIMUM_ALLOWED, NULL, phkResult, NULL );77}787980/******************************************************************************81* RegCreateKeyA [ADVAPI32.@]82*83* See RegCreateKeyW.84*/85LSTATUS WINAPI RegCreateKeyA( HKEY hkey, LPCSTR lpSubKey, PHKEY phkResult )86{87if (!phkResult)88return ERROR_INVALID_PARAMETER;8990return RegCreateKeyExA( hkey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE,91MAXIMUM_ALLOWED, NULL, phkResult, NULL );92}939495/******************************************************************************96* RegCreateKeyTransactedW [ADVAPI32.@]97*/98LSTATUS WINAPI RegCreateKeyTransactedW( HKEY hkey, LPCWSTR name, DWORD reserved, LPWSTR class,99DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,100PHKEY retkey, LPDWORD dispos, HANDLE transaction, PVOID reserved2 )101{102FIXME( "(%p,%s,%lu,%s,%lu,%lu,%p,%p,%p,%p,%p): stub\n", hkey, debugstr_w(name), reserved,103debugstr_w(class), options, access, sa, retkey, dispos, transaction, reserved2 );104return ERROR_CALL_NOT_IMPLEMENTED;105}106107108/******************************************************************************109* RegCreateKeyTransactedA [ADVAPI32.@]110*/111LSTATUS WINAPI RegCreateKeyTransactedA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR class,112DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,113PHKEY retkey, LPDWORD dispos, HANDLE transaction, PVOID reserved2 )114{115FIXME( "(%p,%s,%lu,%s,%lu,%lu,%p,%p,%p,%p,%p): stub\n", hkey, debugstr_a(name), reserved,116debugstr_a(class), options, access, sa, retkey, dispos, transaction, reserved2 );117return ERROR_CALL_NOT_IMPLEMENTED;118}119120121/******************************************************************************122* RegOpenKeyW [ADVAPI32.@]123*124* See RegOpenKeyA.125*/126LSTATUS WINAPI RegOpenKeyW( HKEY hkey, LPCWSTR name, PHKEY retkey )127{128if (!retkey)129return ERROR_INVALID_PARAMETER;130131if (!name || !*name)132{133*retkey = hkey;134return ERROR_SUCCESS;135}136return RegOpenKeyExW( hkey, name, 0, MAXIMUM_ALLOWED, retkey );137}138139140/******************************************************************************141* RegOpenKeyA [ADVAPI32.@]142*143* Open a registry key.144*145* PARAMS146* hkey [I] Handle of parent key to open the new key under147* name [I] Name of the key under hkey to open148* retkey [O] Destination for the resulting Handle149*150* RETURNS151* Success: ERROR_SUCCESS152* Failure: A standard Win32 error code. When retkey is valid, *retkey is set to 0.153*/154LSTATUS WINAPI RegOpenKeyA( HKEY hkey, LPCSTR name, PHKEY retkey )155{156if (!retkey)157return ERROR_INVALID_PARAMETER;158159if (!name || !*name)160{161*retkey = hkey;162return ERROR_SUCCESS;163}164return RegOpenKeyExA( hkey, name, 0, MAXIMUM_ALLOWED, retkey );165}166167168/******************************************************************************169* RegEnumKeyW [ADVAPI32.@]170*171* Enumerates subkeys of the specified open reg key.172*173* PARAMS174* hKey [I] Handle to an open key.175* dwIndex [I] Index of the subkey of hKey to retrieve.176* lpName [O] Name of the subkey.177* cchName [I] Size of lpName in TCHARS.178*179* RETURNS180* Success: ERROR_SUCCESS181* Failure: system error code. If there are no more subkeys available, the182* function returns ERROR_NO_MORE_ITEMS.183*/184LSTATUS WINAPI RegEnumKeyW( HKEY hkey, DWORD index, LPWSTR name, DWORD name_len )185{186return RegEnumKeyExW( hkey, index, name, &name_len, NULL, NULL, NULL, NULL );187}188189190/******************************************************************************191* RegEnumKeyA [ADVAPI32.@]192*193* See RegEnumKeyW.194*/195LSTATUS WINAPI RegEnumKeyA( HKEY hkey, DWORD index, LPSTR name, DWORD name_len )196{197return RegEnumKeyExA( hkey, index, name, &name_len, NULL, NULL, NULL, NULL );198}199200201/******************************************************************************202* RegQueryMultipleValuesA [ADVAPI32.@]203*204* Retrieves the type and data for a list of value names associated with a key.205*206* PARAMS207* hKey [I] Handle to an open key.208* val_list [O] Array of VALENT structures that describes the entries.209* num_vals [I] Number of elements in val_list.210* lpValueBuf [O] Pointer to a buffer that receives the data for each value.211* ldwTotsize [I/O] Size of lpValueBuf.212*213* RETURNS214* Success: ERROR_SUCCESS. ldwTotsize contains num bytes copied.215* Failure: nonzero error code from Winerror.h ldwTotsize contains num needed216* bytes.217*/218LSTATUS WINAPI RegQueryMultipleValuesA( HKEY hkey, PVALENTA val_list, DWORD num_vals,219LPSTR lpValueBuf, LPDWORD ldwTotsize )220{221unsigned int i;222DWORD maxBytes = *ldwTotsize;223LSTATUS status;224LPSTR bufptr = lpValueBuf;225*ldwTotsize = 0;226227TRACE("(%p,%p,%ld,%p,%p=%ld)\n", hkey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);228229for(i=0; i < num_vals; ++i)230{231232val_list[i].ve_valuelen=0;233status = RegQueryValueExA(hkey, val_list[i].ve_valuename, NULL, NULL, NULL, &val_list[i].ve_valuelen);234if(status != ERROR_SUCCESS)235{236return status;237}238239if(lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)240{241status = RegQueryValueExA(hkey, val_list[i].ve_valuename, NULL, &val_list[i].ve_type,242(LPBYTE)bufptr, &val_list[i].ve_valuelen);243if(status != ERROR_SUCCESS)244{245return status;246}247248val_list[i].ve_valueptr = (DWORD_PTR)bufptr;249250bufptr += val_list[i].ve_valuelen;251}252253*ldwTotsize += val_list[i].ve_valuelen;254}255return lpValueBuf != NULL && *ldwTotsize <= maxBytes ? ERROR_SUCCESS : ERROR_MORE_DATA;256}257258259/******************************************************************************260* RegQueryMultipleValuesW [ADVAPI32.@]261*262* See RegQueryMultipleValuesA.263*/264LSTATUS WINAPI RegQueryMultipleValuesW( HKEY hkey, PVALENTW val_list, DWORD num_vals,265LPWSTR lpValueBuf, LPDWORD ldwTotsize )266{267unsigned int i;268DWORD maxBytes = *ldwTotsize;269LSTATUS status;270LPSTR bufptr = (LPSTR)lpValueBuf;271*ldwTotsize = 0;272273TRACE("(%p,%p,%ld,%p,%p=%ld)\n", hkey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);274275for(i=0; i < num_vals; ++i)276{277val_list[i].ve_valuelen=0;278status = RegQueryValueExW(hkey, val_list[i].ve_valuename, NULL, NULL, NULL, &val_list[i].ve_valuelen);279if(status != ERROR_SUCCESS)280{281return status;282}283284if(lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)285{286status = RegQueryValueExW(hkey, val_list[i].ve_valuename, NULL, &val_list[i].ve_type,287(LPBYTE)bufptr, &val_list[i].ve_valuelen);288if(status != ERROR_SUCCESS)289{290return status;291}292293val_list[i].ve_valueptr = (DWORD_PTR)bufptr;294295bufptr += val_list[i].ve_valuelen;296}297298*ldwTotsize += val_list[i].ve_valuelen;299}300return lpValueBuf != NULL && *ldwTotsize <= maxBytes ? ERROR_SUCCESS : ERROR_MORE_DATA;301}302303304/******************************************************************************305* RegQueryReflectionKey [ADVAPI32.@]306*/307LONG WINAPI RegQueryReflectionKey( HKEY hkey, BOOL *is_reflection_disabled )308{309FIXME( "%p, %p stub\n", hkey, is_reflection_disabled );310*is_reflection_disabled = TRUE;311return ERROR_CALL_NOT_IMPLEMENTED;312}313314315/******************************************************************************316* RegDeleteKeyW [ADVAPI32.@]317*318* See RegDeleteKeyA.319*/320LSTATUS WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name )321{322return RegDeleteKeyExW( hkey, name, 0, 0 );323}324325326/******************************************************************************327* RegDeleteKeyA [ADVAPI32.@]328*329* Delete a registry key.330*331* PARAMS332* hkey [I] Handle to parent key containing the key to delete333* name [I] Name of the key user hkey to delete334*335* NOTES336*337* MSDN is wrong when it says that hkey must be opened with the DELETE access338* right. In reality, it opens a new handle with DELETE access.339*340* RETURNS341* Success: ERROR_SUCCESS342* Failure: Error code343*/344LSTATUS WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )345{346return RegDeleteKeyExA( hkey, name, 0, 0 );347}348349350/******************************************************************************351* RegSetValueW [ADVAPI32.@]352*353* Sets the data for the default or unnamed value of a reg key.354*355* PARAMS356* hkey [I] Handle to an open key.357* subkey [I] Name of a subkey of hKey.358* type [I] Type of information to store.359* data [I] String that contains the data to set for the default value.360* count [I] Ignored.361*362* RETURNS363* Success: ERROR_SUCCESS364* Failure: nonzero error code from Winerror.h365*/366LSTATUS WINAPI RegSetValueW( HKEY hkey, LPCWSTR subkey, DWORD type, LPCWSTR data, DWORD count )367{368TRACE("(%p,%s,%ld,%s,%ld)\n", hkey, debugstr_w(subkey), type, debugstr_w(data), count );369370if (type != REG_SZ || !data) return ERROR_INVALID_PARAMETER;371372return RegSetKeyValueW( hkey, subkey, NULL, type, data, (lstrlenW(data) + 1)*sizeof(WCHAR) );373}374375/******************************************************************************376* RegSetValueA [ADVAPI32.@]377*378* See RegSetValueW.379*/380LSTATUS WINAPI RegSetValueA( HKEY hkey, LPCSTR subkey, DWORD type, LPCSTR data, DWORD count )381{382TRACE("(%p,%s,%ld,%s,%ld)\n", hkey, debugstr_a(subkey), type, debugstr_a(data), count );383384if (type != REG_SZ || !data) return ERROR_INVALID_PARAMETER;385386return RegSetKeyValueA( hkey, subkey, NULL, type, data, strlen(data) + 1 );387}388389390/******************************************************************************391* RegQueryValueW [ADVAPI32.@]392*393* Retrieves the data associated with the default or unnamed value of a key.394*395* PARAMS396* hkey [I] Handle to an open key.397* name [I] Name of the subkey of hKey.398* data [O] Receives the string associated with the default value399* of the key.400* count [I/O] Size of lpValue in bytes.401*402* RETURNS403* Success: ERROR_SUCCESS404* Failure: nonzero error code from Winerror.h405*/406LSTATUS WINAPI RegQueryValueW( HKEY hkey, LPCWSTR name, LPWSTR data, LPLONG count )407{408DWORD ret;409HKEY subkey = hkey;410411TRACE("(%p,%s,%p,%ld)\n", hkey, debugstr_w(name), data, count ? *count : 0 );412413if (name && name[0])414{415if ((ret = RegOpenKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;416}417ret = RegQueryValueExW( subkey, NULL, NULL, NULL, (LPBYTE)data, (LPDWORD)count );418if (subkey != hkey) RegCloseKey( subkey );419if (ret == ERROR_FILE_NOT_FOUND)420{421/* return empty string if default value not found */422if (data) *data = 0;423if (count) *count = sizeof(WCHAR);424ret = ERROR_SUCCESS;425}426return ret;427}428429430/******************************************************************************431* RegQueryValueA [ADVAPI32.@]432*433* See RegQueryValueW.434*/435LSTATUS WINAPI RegQueryValueA( HKEY hkey, LPCSTR name, LPSTR data, LPLONG count )436{437DWORD ret;438HKEY subkey = hkey;439440TRACE("(%p,%s,%p,%ld)\n", hkey, debugstr_a(name), data, count ? *count : 0 );441442if (name && name[0])443{444if ((ret = RegOpenKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;445}446ret = RegQueryValueExA( subkey, NULL, NULL, NULL, (LPBYTE)data, (LPDWORD)count );447if (subkey != hkey) RegCloseKey( subkey );448if (ret == ERROR_FILE_NOT_FOUND)449{450/* return empty string if default value not found */451if (data) *data = 0;452if (count) *count = 1;453ret = ERROR_SUCCESS;454}455return ret;456}457458459/******************************************************************************460* RegSaveKeyW [ADVAPI32.@]461*462* Save a key and all of its subkeys and values to a new file in the standard format.463*464* PARAMS465* hkey [I] Handle of key where save begins466* lpFile [I] Address of filename to save to467* sa [I] Address of security structure468*469* RETURNS470* Success: ERROR_SUCCESS471* Failure: nonzero error code from Winerror.h472*/473LSTATUS WINAPI RegSaveKeyW( HKEY hkey, LPCWSTR file, LPSECURITY_ATTRIBUTES sa )474{475return RegSaveKeyExW(hkey, file, sa, 0);476}477478479/******************************************************************************480* RegSaveKeyA [ADVAPI32.@]481*482* See RegSaveKeyW.483*/484LSTATUS WINAPI RegSaveKeyA( HKEY hkey, LPCSTR file, LPSECURITY_ATTRIBUTES sa )485{486return RegSaveKeyExA(hkey, file, sa, 0);487}488489490/******************************************************************************491* RegReplaceKeyW [ADVAPI32.@]492*493* Replace the file backing a registry key and all its subkeys with another file.494*495* PARAMS496* hkey [I] Handle of open key497* lpSubKey [I] Address of name of subkey498* lpNewFile [I] Address of filename for file with new data499* lpOldFile [I] Address of filename for backup file500*501* RETURNS502* Success: ERROR_SUCCESS503* Failure: nonzero error code from Winerror.h504*/505LSTATUS WINAPI RegReplaceKeyW( HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpNewFile,506LPCWSTR lpOldFile )507{508FIXME("(%p,%s,%s,%s): stub\n", hkey, debugstr_w(lpSubKey),509debugstr_w(lpNewFile),debugstr_w(lpOldFile));510return ERROR_SUCCESS;511}512513514/******************************************************************************515* RegRenameKey [ADVAPI32.@]516*517*/518LSTATUS WINAPI RegRenameKey( HKEY hkey, LPCWSTR subkey_name, LPCWSTR new_name )519{520UNICODE_STRING str;521LSTATUS ret;522HKEY subkey;523524TRACE("%p, %s, %s.\n", hkey, debugstr_w(subkey_name), debugstr_w(new_name));525526RtlInitUnicodeString(&str, new_name);527528if (!subkey_name)529return RtlNtStatusToDosError( NtRenameKey( hkey, &str ));530531if ((ret = RegOpenKeyExW( hkey, subkey_name, 0, KEY_WRITE, &subkey )))532return ret;533534ret = RtlNtStatusToDosError( NtRenameKey( subkey, &str ));535RegCloseKey( subkey );536537return ret;538}539540541/******************************************************************************542* RegReplaceKeyA [ADVAPI32.@]543*544* See RegReplaceKeyW.545*/546LSTATUS WINAPI RegReplaceKeyA( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile,547LPCSTR lpOldFile )548{549UNICODE_STRING lpSubKeyW;550UNICODE_STRING lpNewFileW;551UNICODE_STRING lpOldFileW;552LONG ret;553554RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW, lpSubKey );555RtlCreateUnicodeStringFromAsciiz( &lpOldFileW, lpOldFile );556RtlCreateUnicodeStringFromAsciiz( &lpNewFileW, lpNewFile );557ret = RegReplaceKeyW( hkey, lpSubKeyW.Buffer, lpNewFileW.Buffer, lpOldFileW.Buffer );558RtlFreeUnicodeString( &lpOldFileW );559RtlFreeUnicodeString( &lpNewFileW );560RtlFreeUnicodeString( &lpSubKeyW );561return ret;562}563564565/******************************************************************************566* RegConnectRegistryW [ADVAPI32.@]567*568* Establish a connection to a predefined registry key on another computer.569*570* PARAMS571* lpMachineName [I] Address of name of remote computer572* hHey [I] Predefined registry handle573* phkResult [I] Address of buffer for remote registry handle574*575* RETURNS576* Success: ERROR_SUCCESS577* Failure: nonzero error code from Winerror.h578*/579LSTATUS WINAPI RegConnectRegistryW( LPCWSTR lpMachineName, HKEY hKey,580PHKEY phkResult )581{582LONG ret;583584TRACE("(%s,%p,%p)\n",debugstr_w(lpMachineName), hKey, phkResult);585586if (!lpMachineName || !*lpMachineName) {587/* Use the local machine name */588ret = RegOpenKeyW( hKey, NULL, phkResult );589}590else {591WCHAR compName[MAX_COMPUTERNAME_LENGTH + 1];592DWORD len = ARRAY_SIZE( compName );593594/* MSDN says lpMachineName must start with \\ : not so */595if( lpMachineName[0] == '\\' && lpMachineName[1] == '\\')596lpMachineName += 2;597if (GetComputerNameW(compName, &len))598{599if (!wcsicmp(lpMachineName, compName))600ret = RegOpenKeyW(hKey, NULL, phkResult);601else602{603FIXME("Connect to %s is not supported.\n",debugstr_w(lpMachineName));604ret = ERROR_BAD_NETPATH;605}606}607else608ret = GetLastError();609}610return ret;611}612613614/******************************************************************************615* RegConnectRegistryA [ADVAPI32.@]616*617* See RegConnectRegistryW.618*/619LSTATUS WINAPI RegConnectRegistryA( LPCSTR machine, HKEY hkey, PHKEY reskey )620{621UNICODE_STRING machineW;622LONG ret;623624RtlCreateUnicodeStringFromAsciiz( &machineW, machine );625ret = RegConnectRegistryW( machineW.Buffer, hkey, reskey );626RtlFreeUnicodeString( &machineW );627return ret;628}629630631/******************************************************************************632* RegDisablePredefinedCache [ADVAPI32.@]633*634* Disables the caching of the HKEY_CURRENT_USER key for the process.635*636* PARAMS637* None.638*639* RETURNS640* Success: ERROR_SUCCESS641* Failure: nonzero error code from Winerror.h642*643* NOTES644* This is useful for services that use impersonation.645*/646LSTATUS WINAPI RegDisablePredefinedCache(void)647{648return RtlNtStatusToDosError( DisablePredefinedHandleTableInternal( HKEY_CURRENT_USER ));649}650651652/******************************************************************************653* RegCopyTreeA [ADVAPI32.@]654*655*/656LONG WINAPI RegCopyTreeA( HKEY hsrc, const char *subkey, HKEY hdst )657{658UNICODE_STRING subkeyW;659LONG ret;660661if (subkey) RtlCreateUnicodeStringFromAsciiz( &subkeyW, subkey );662else subkeyW.Buffer = NULL;663ret = RegCopyTreeW( hsrc, subkeyW.Buffer, hdst );664RtlFreeUnicodeString( &subkeyW );665return ret;666}667668669/******************************************************************************670* RegEnableReflectionKey [ADVAPI32.@]671*672*/673LONG WINAPI RegEnableReflectionKey(HKEY base)674{675FIXME("%p: stub\n", base);676return ERROR_CALL_NOT_IMPLEMENTED;677}678679680/******************************************************************************681* RegDisableReflectionKey [ADVAPI32.@]682*683*/684LONG WINAPI RegDisableReflectionKey(HKEY base)685{686FIXME("%p: stub\n", base);687return ERROR_SUCCESS;688}689690691