1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//
5// --------------------------------------------------------------------------------------------------
6// CLRConfig.h
7//
8
9//
10// Unified method of accessing configuration values from environment variables, registry and config file(s).
11// This class replaces all GetConfigDWORD and GetConfigString methods in EEConfig and REGUTIL. To define a
12// flag, add an entry in the table in file:CLRConfigValues.h.
13//
14//
15//
16//
17// --------------------------------------------------------------------------------------------------
18
19
20#include "utilcode.h"
21#include "holder.h"
22
23#ifndef __CLRConfig_h__
24#define __CLRConfig_h__
25
26class CLRConfig
27{
28public:
29 //
30 // Types
31 //
32
33 // Setting each option results in some change to the config value lookup method. Default behavior is (in
34 // the following order):
35 // * Look at environment variables (prepending COMPlus to the name)
36 // * Look at the framework registry keys (HKCU\Software\Microsoft\.NETFramework then
37 // HKLM\Software\Microsoft\.NETFramework)
38 // * Look at the available config files (system, application, host and user). For details see TODO:
39 // Link to BOTR documentation
40 enum LookupOptions {
41 // If set, don't look in environment variables.
42 IgnoreEnv = 0x1,
43 // If set, do not prepend "COMPlus_" when doing environment variable lookup.
44 DontPrependCOMPlus_ = 0x2,
45 // If set, don't look in HKLM in the registry.
46 IgnoreHKLM = 0x4,
47 // If set, don't look in HKCU in the registry.
48 IgnoreHKCU = 0x8,
49 // If set, don't look in any config files
50 IgnoreConfigFiles = 0x10,
51 // If set, look in config file(s) before looking in env/registry.
52 FavorConfigFile = 0x20,
53 // If set, look only in the system config file, ignoring other config files.
54 // (This option does not affect environment variable and registry lookups)
55 ConfigFile_SystemOnly = 0x40,
56 // If set, reverse the order of config file lookups (application config file first).
57 // (This option does not affect environment variable and registry lookups)
58 ConfigFile_ApplicationFirst = 0x80,
59 // Remove any whitespace at beginning and end of value. (Only applicable for
60 // *string* configuration values.)
61 TrimWhiteSpaceFromStringValue = 0x100,
62
63 // Legacy REGUTIL-style lookup.
64 REGUTIL_default = IgnoreConfigFiles,
65 // Legacy EEConfig-style lookup.
66 EEConfig_default = 0,
67 };
68
69 // Function pointer definition used for calling EEConfig::GetConfigValueCallback .
70 typedef HRESULT (* GetConfigValueFunction)
71 (__in_z LPCWSTR /*pKey*/, __deref_out_opt LPCWSTR* /*value*/, BOOL /*systemOnly*/, BOOL /*applicationFirst*/);
72
73 // Struct used to store information about where/how to find a Config DWORD.
74 // NOTE: Please do NOT create instances of this struct. Use the macros in file:CLRConfigValues.h instead.
75 typedef struct ConfigDWORDInfo
76 {
77 LPCWSTR name;
78 DWORD defaultValue;
79 LookupOptions options;
80 } ConfigDWORDInfo;
81
82 // Struct used to store information about where/how to find a Config String.
83 // NOTE: Please do NOT create instances of this struct. Use the macros in file:CLRConfigValues.h instead.
84 typedef struct ConfigStringInfo
85 {
86 LPCWSTR name;
87 LookupOptions options;
88 } ConfigStringInfo;
89
90 //
91 // Declaring structs using the macro table in CLRConfigValues.h
92 //
93
94 // These macros declare ConfigDWORDInfo structs.
95 #define RETAIL_CONFIG_DWORD_INFO(symbol, name, defaultValue, description) \
96 static const ConfigDWORDInfo symbol;
97 #define RETAIL_CONFIG_DWORD_INFO_EX(symbol, name, defaultValue, description, lookupOptions) \
98 static const ConfigDWORDInfo symbol;
99
100 // These macros declare ConfigStringInfo structs.
101 #define RETAIL_CONFIG_STRING_INFO(symbol, name, description) \
102 static const ConfigStringInfo symbol;
103 #define RETAIL_CONFIG_STRING_INFO_EX(symbol, name, description, lookupOptions) \
104 static const ConfigStringInfo symbol;
105
106 // TEMPORARY macros that declare strings. These are used for config value accesses that haven't been
107 // moved over to CLRConfig yet. Once all accesses have been moved, these macros (and corresponding
108 // instantiations in file:../utilcode/CLRConfig.cpp) should be removed.
109 #define RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(symbol, name, description) \
110 static const LPCWSTR symbol;
111 #define RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(symbol, name, description) \
112 static const LPCWSTR symbol;
113
114 //
115 // Debug versions of the macros
116 //
117#ifdef _DEBUG
118 #define CONFIG_DWORD_INFO(symbol, name, defaultValue, description) \
119 static const ConfigDWORDInfo symbol;
120 #define CONFIG_DWORD_INFO_EX(symbol, name, defaultValue, description, lookupOptions) \
121 static const ConfigDWORDInfo symbol;
122 #define CONFIG_STRING_INFO(symbol, name, description) \
123 static const ConfigStringInfo symbol;
124 #define CONFIG_STRING_INFO_EX(symbol, name, description, lookupOptions) \
125 static const ConfigStringInfo symbol;
126 #define CONFIG_DWORD_INFO_DIRECT_ACCESS(symbol, name, description) \
127 static const LPCWSTR symbol;
128 #define CONFIG_STRING_INFO_DIRECT_ACCESS(symbol, name, description) \
129 static const LPCWSTR symbol;
130#else
131 #define CONFIG_DWORD_INFO(symbol, name, defaultValue, description)
132 #define CONFIG_DWORD_INFO_EX(symbol, name, defaultValue, description, lookupOptions)
133 #define CONFIG_STRING_INFO(symbol, name, description)
134 #define CONFIG_STRING_INFO_EX(symbol, name, description, lookupOptions)
135 #define CONFIG_DWORD_INFO_DIRECT_ACCESS(symbol, name, description)
136 #define CONFIG_STRING_INFO_DIRECT_ACCESS(symbol, name, description)
137#endif // _DEBUG
138 // Now that we have defined what what the macros in file:CLRConfigValues.h mean, include it to generate the code.
139 #include "clrconfigvalues.h"
140
141 #undef RETAIL_CONFIG_DWORD_INFO
142 #undef RETAIL_CONFIG_STRING_INFO
143 #undef RETAIL_CONFIG_DWORD_INFO_EX
144 #undef RETAIL_CONFIG_STRING_INFO_EX
145 #undef RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS
146 #undef RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS
147 #undef CONFIG_DWORD_INFO
148 #undef CONFIG_STRING_INFO
149 #undef CONFIG_DWORD_INFO_EX
150 #undef CONFIG_STRING_INFO_EX
151 #undef CONFIG_DWORD_INFO_DIRECT_ACCESS
152 #undef CONFIG_STRING_INFO_DIRECT_ACCESS
153
154 //
155 // Methods to do config value (DWORD and String) lookups.
156 //
157 static BOOL IsConfigEnabled(const ConfigDWORDInfo & info);
158
159 // Look up a DWORD config value.
160 static DWORD GetConfigValue(const ConfigDWORDInfo & info);
161
162 // Look up a DWORD config value.
163 static DWORD GetConfigValue(const ConfigDWORDInfo & info, bool acceptExplicitDefaultFromRegutil, /* [Out] */ bool *isDefault);
164
165 // Look up a string config value.
166 // You own the string that's returned.
167 static LPWSTR GetConfigValue(const ConfigStringInfo & info);
168
169 // Look up a string config value, passing it out through a pointer reference. Reports out of memory
170 // errors (HRESULT E_OUTOFMEMORY).
171 // You own the string that's returned.
172 static HRESULT GetConfigValue(const ConfigStringInfo & info, __deref_out_z LPWSTR * outVal);
173
174 //
175 // Check whether an option is specified (e.g. explicitly listed) in any of the CLRConfig
176 // locations: environment or registry (with or without COMPlus_) or any config file.
177 // The result is therefore a conservative approximation (some settings do not actually
178 // take effect everywhere and no setting is valid both with and without COMPlus_)
179 //
180 static BOOL IsConfigOptionSpecified(LPCWSTR name);
181
182 // Free a string returned by GetConfigValue
183 static void FreeConfigString(__in __in_z LPWSTR name);
184
185 // Register EEConfig's GetConfigValueCallback function so CLRConfig can look in config files.
186 static void RegisterGetConfigValueCallback(GetConfigValueFunction func);
187
188private:
189 // Function pointer to EEConfig's GetConfigValueCallback function (can't static bind from utilcode to VM)
190 static GetConfigValueFunction s_GetConfigValueCallback;
191
192
193 // Helper method to translate LookupOptions to REGUTIL::CORConfigLevel
194 static REGUTIL::CORConfigLevel GetConfigLevel(LookupOptions options);
195
196 //
197 // Helper methods.
198 //
199
200 // Helper method to check if a certain option is set in a ConfigDWORDInfo struct.
201 static inline BOOL CheckLookupOption(const ConfigDWORDInfo & info, LookupOptions option)
202 {
203 LIMITED_METHOD_CONTRACT;
204 return ((info.options & option) == option) ? TRUE : FALSE;
205 }
206
207 // Helper method to check if a certain option is set in a ConfigStringInfo struct.
208 static inline BOOL CheckLookupOption(const ConfigStringInfo & info, LookupOptions option)
209 {
210 LIMITED_METHOD_CONTRACT;
211 return ((info.options & option) == option) ? TRUE : FALSE;
212 }
213
214 // Helper method to check if a certain option is set in an options enum.
215 static inline BOOL CheckLookupOption(LookupOptions infoOptions, LookupOptions optionToCheck)
216 {
217 LIMITED_METHOD_CONTRACT;
218 return ((infoOptions & optionToCheck) == optionToCheck) ? TRUE : FALSE;
219 }
220
221 static HRESULT TrimWhiteSpace(LPCWSTR wszOrig, __deref_out_z LPWSTR * pwszTrimmed);
222};
223
224inline CLRConfig::LookupOptions operator|(CLRConfig::LookupOptions lhs, CLRConfig::LookupOptions rhs)
225{
226 return static_cast<CLRConfig::LookupOptions>(static_cast<DWORD>(lhs) | static_cast<DWORD>(rhs));
227}
228
229typedef Wrapper<LPWSTR, DoNothing, CLRConfig::FreeConfigString, NULL> CLRConfigStringHolder;
230
231#endif //__CLRConfig_h__
232