1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2017 - ROLI Ltd.
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21 */
22
23 namespace juce
24 {
25
26 struct RegistryKeyWrapper
27 {
RegistryKeyWrapperjuce::RegistryKeyWrapper28 RegistryKeyWrapper (String name, bool createForWriting, DWORD wow64Flags)
29 {
30 if (HKEY rootKey = getRootKey (name))
31 {
32 name = name.substring (name.indexOfChar ('\\') + 1);
33
34 auto lastSlash = name.lastIndexOfChar ('\\');
35 valueName = name.substring (lastSlash + 1);
36 wideCharValueName = valueName.toWideCharPointer();
37
38 name = name.substring (0, lastSlash);
39 auto wideCharName = name.toWideCharPointer();
40 DWORD result;
41
42 if (createForWriting)
43 RegCreateKeyEx (rootKey, wideCharName, 0, 0, REG_OPTION_NON_VOLATILE,
44 KEY_WRITE | KEY_QUERY_VALUE | wow64Flags, 0, &key, &result);
45 else
46 RegOpenKeyEx (rootKey, wideCharName, 0, KEY_READ | wow64Flags, &key);
47 }
48 }
49
~RegistryKeyWrapperjuce::RegistryKeyWrapper50 ~RegistryKeyWrapper()
51 {
52 if (key != nullptr)
53 RegCloseKey (key);
54 }
55
getRootKeyjuce::RegistryKeyWrapper56 static HKEY getRootKey (const String& name) noexcept
57 {
58 if (name.startsWithIgnoreCase ("HKEY_CURRENT_USER\\")) return HKEY_CURRENT_USER;
59 if (name.startsWithIgnoreCase ("HKCU\\")) return HKEY_CURRENT_USER;
60 if (name.startsWithIgnoreCase ("HKEY_LOCAL_MACHINE\\")) return HKEY_LOCAL_MACHINE;
61 if (name.startsWithIgnoreCase ("HKLM\\")) return HKEY_LOCAL_MACHINE;
62 if (name.startsWithIgnoreCase ("HKEY_CLASSES_ROOT\\")) return HKEY_CLASSES_ROOT;
63 if (name.startsWithIgnoreCase ("HKCR\\")) return HKEY_CLASSES_ROOT;
64 if (name.startsWithIgnoreCase ("HKEY_USERS\\")) return HKEY_USERS;
65 if (name.startsWithIgnoreCase ("HKU\\")) return HKEY_USERS;
66
67 jassertfalse; // The name starts with an unknown root key (or maybe an old Win9x type)
68 return 0;
69 }
70
setValuejuce::RegistryKeyWrapper71 static bool setValue (const String& regValuePath, const DWORD type,
72 const void* data, size_t dataSize, const DWORD wow64Flags)
73 {
74 const RegistryKeyWrapper key (regValuePath, true, wow64Flags);
75
76 return key.key != nullptr
77 && RegSetValueEx (key.key, key.wideCharValueName, 0, type,
78 reinterpret_cast<const BYTE*> (data),
79 (DWORD) dataSize) == ERROR_SUCCESS;
80 }
81
getBinaryValuejuce::RegistryKeyWrapper82 static uint32 getBinaryValue (const String& regValuePath, MemoryBlock& result, DWORD wow64Flags)
83 {
84 const RegistryKeyWrapper key (regValuePath, false, wow64Flags);
85
86 if (key.key != nullptr)
87 {
88 for (unsigned long bufferSize = 1024; ; bufferSize *= 2)
89 {
90 result.setSize (bufferSize, false);
91 DWORD type = REG_NONE;
92
93 auto err = RegQueryValueEx (key.key, key.wideCharValueName, 0, &type,
94 (LPBYTE) result.getData(), &bufferSize);
95
96 if (err == ERROR_SUCCESS)
97 {
98 result.setSize (bufferSize, false);
99 return type;
100 }
101
102 if (err != ERROR_MORE_DATA)
103 break;
104 }
105 }
106
107 return REG_NONE;
108 }
109
getValuejuce::RegistryKeyWrapper110 static String getValue (const String& regValuePath, const String& defaultValue, DWORD wow64Flags)
111 {
112 MemoryBlock buffer;
113
114 switch (getBinaryValue (regValuePath, buffer, wow64Flags))
115 {
116 case REG_SZ: return static_cast<const WCHAR*> (buffer.getData());
117 case REG_DWORD: return String ((int) *reinterpret_cast<const DWORD*> (buffer.getData()));
118 default: break;
119 }
120
121 return defaultValue;
122 }
123
keyExistsjuce::RegistryKeyWrapper124 static bool keyExists (const String& regKeyPath, const DWORD wow64Flags)
125 {
126 return RegistryKeyWrapper (regKeyPath + "\\", false, wow64Flags).key != nullptr;
127 }
128
valueExistsjuce::RegistryKeyWrapper129 static bool valueExists (const String& regValuePath, const DWORD wow64Flags)
130 {
131 const RegistryKeyWrapper key (regValuePath, false, wow64Flags);
132
133 if (key.key == nullptr)
134 return false;
135
136 unsigned char buffer [512];
137 unsigned long bufferSize = sizeof (buffer);
138 DWORD type = 0;
139
140 auto result = RegQueryValueEx (key.key, key.wideCharValueName,
141 0, &type, buffer, &bufferSize);
142
143 return result == ERROR_SUCCESS || result == ERROR_MORE_DATA;
144 }
145
146 HKEY key = nullptr;
147 const wchar_t* wideCharValueName = nullptr;
148 String valueName;
149
150 JUCE_DECLARE_NON_COPYABLE (RegistryKeyWrapper)
151 };
152
getBinaryValue(const String & regValuePath,MemoryBlock & result,WoW64Mode mode)153 uint32 JUCE_CALLTYPE WindowsRegistry::getBinaryValue (const String& regValuePath, MemoryBlock& result, WoW64Mode mode)
154 {
155 return RegistryKeyWrapper::getBinaryValue (regValuePath, result, (DWORD) mode);
156 }
157
getValue(const String & regValuePath,const String & defaultValue,WoW64Mode mode)158 String JUCE_CALLTYPE WindowsRegistry::getValue (const String& regValuePath, const String& defaultValue, WoW64Mode mode)
159 {
160 return RegistryKeyWrapper::getValue (regValuePath, defaultValue, (DWORD) mode);
161 }
162
setValue(const String & regValuePath,const String & value,WoW64Mode mode)163 bool JUCE_CALLTYPE WindowsRegistry::setValue (const String& regValuePath, const String& value, WoW64Mode mode)
164 {
165 return RegistryKeyWrapper::setValue (regValuePath, REG_SZ, value.toWideCharPointer(),
166 CharPointer_UTF16::getBytesRequiredFor (value.getCharPointer()), mode);
167 }
168
setValue(const String & regValuePath,const uint32 value,WoW64Mode mode)169 bool JUCE_CALLTYPE WindowsRegistry::setValue (const String& regValuePath, const uint32 value, WoW64Mode mode)
170 {
171 return RegistryKeyWrapper::setValue (regValuePath, REG_DWORD, &value, sizeof (value), (DWORD) mode);
172 }
173
setValue(const String & regValuePath,const uint64 value,WoW64Mode mode)174 bool JUCE_CALLTYPE WindowsRegistry::setValue (const String& regValuePath, const uint64 value, WoW64Mode mode)
175 {
176 return RegistryKeyWrapper::setValue (regValuePath, REG_QWORD, &value, sizeof (value), (DWORD) mode);
177 }
178
setValue(const String & regValuePath,const MemoryBlock & value,WoW64Mode mode)179 bool JUCE_CALLTYPE WindowsRegistry::setValue (const String& regValuePath, const MemoryBlock& value, WoW64Mode mode)
180 {
181 return RegistryKeyWrapper::setValue (regValuePath, REG_BINARY, value.getData(), value.getSize(), (DWORD) mode);
182 }
183
valueExists(const String & regValuePath,WoW64Mode mode)184 bool JUCE_CALLTYPE WindowsRegistry::valueExists (const String& regValuePath, WoW64Mode mode)
185 {
186 return RegistryKeyWrapper::valueExists (regValuePath, (DWORD) mode);
187 }
188
keyExists(const String & regKeyPath,WoW64Mode mode)189 bool JUCE_CALLTYPE WindowsRegistry::keyExists (const String& regKeyPath, WoW64Mode mode)
190 {
191 return RegistryKeyWrapper::keyExists (regKeyPath, (DWORD) mode);
192 }
193
deleteValue(const String & regValuePath,WoW64Mode mode)194 bool JUCE_CALLTYPE WindowsRegistry::deleteValue (const String& regValuePath, WoW64Mode mode)
195 {
196 const RegistryKeyWrapper key (regValuePath, true, (DWORD) mode);
197
198 return key.key != nullptr && RegDeleteValue (key.key, key.wideCharValueName) == ERROR_SUCCESS;
199 }
200
deleteKeyNonRecursive(const String & regKeyPath,WindowsRegistry::WoW64Mode mode)201 static bool deleteKeyNonRecursive (const String& regKeyPath, WindowsRegistry::WoW64Mode mode)
202 {
203 const RegistryKeyWrapper key (regKeyPath, true, (DWORD) mode);
204
205 return key.key != nullptr && RegDeleteKey (key.key, key.wideCharValueName) == ERROR_SUCCESS;
206 }
207
deleteKey(const String & regKeyPath,WoW64Mode mode)208 bool JUCE_CALLTYPE WindowsRegistry::deleteKey (const String& regKeyPath, WoW64Mode mode)
209 {
210 if (deleteKeyNonRecursive (regKeyPath, mode))
211 return true;
212
213 for (const RegistryKeyWrapper key (regKeyPath + "\\", false, (DWORD) mode);;)
214 {
215 wchar_t subKey[MAX_PATH + 1] = {};
216 DWORD subKeySize = MAX_PATH;
217
218 if (RegEnumKeyEx (key.key, 0, subKey, &subKeySize, nullptr, nullptr, nullptr, nullptr) != ERROR_SUCCESS
219 || ! deleteKey (regKeyPath + "\\" + String (subKey), mode))
220 break;
221 }
222
223 return deleteKeyNonRecursive (regKeyPath, mode);
224 }
225
registerFileAssociation(const String & fileExtension,const String & symbolicDescription,const String & fullDescription,const File & targetExecutable,const int iconResourceNumber,const bool registerForCurrentUserOnly,WoW64Mode mode)226 bool JUCE_CALLTYPE WindowsRegistry::registerFileAssociation (const String& fileExtension,
227 const String& symbolicDescription,
228 const String& fullDescription,
229 const File& targetExecutable,
230 const int iconResourceNumber,
231 const bool registerForCurrentUserOnly,
232 WoW64Mode mode)
233 {
234 auto root = registerForCurrentUserOnly ? "HKEY_CURRENT_USER\\Software\\Classes\\"
235 : "HKEY_CLASSES_ROOT\\";
236 auto key = root + symbolicDescription;
237
238 return setValue (root + fileExtension + "\\", symbolicDescription, mode)
239 && setValue (key + "\\", fullDescription, mode)
240 && setValue (key + "\\shell\\open\\command\\", targetExecutable.getFullPathName() + " \"%1\"", mode)
241 && (iconResourceNumber == 0
242 || setValue (key + "\\DefaultIcon\\",
243 targetExecutable.getFullPathName() + "," + String (iconResourceNumber)));
244 }
245
246 // These methods are deprecated:
getValueWow64(const String & p,const String & defVal)247 String WindowsRegistry::getValueWow64 (const String& p, const String& defVal) { return getValue (p, defVal, WoW64_64bit); }
valueExistsWow64(const String & p)248 bool WindowsRegistry::valueExistsWow64 (const String& p) { return valueExists (p, WoW64_64bit); }
keyExistsWow64(const String & p)249 bool WindowsRegistry::keyExistsWow64 (const String& p) { return keyExists (p, WoW64_64bit); }
250
251 } // namespace juce
252