00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "windowsRegistry.h"
00016 #include "config_express.h"
00017 #include "textEncoder.h"
00018
00019 #if defined(WIN32_VC)
00020 #define WIN32_LEAN_AND_MEAN
00021 #include <windows.h>
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 bool WindowsRegistry::
00034 set_string_value(const string &key, const string &name, const string &value,
00035 WindowsRegistry::RegLevel rl)
00036 {
00037 TextEncoder encoder;
00038 wstring wvalue = encoder.decode_text(value);
00039
00040 bool okflag = true;
00041
00042
00043
00044
00045
00046
00047
00048 wvalue += (wchar_t)0;
00049 int mb_result_len =
00050 WideCharToMultiByte(CP_ACP, 0,
00051 wvalue.data(), wvalue.length(),
00052 NULL, 0,
00053 NULL, NULL);
00054 if (mb_result_len == 0) {
00055 express_cat.error()
00056 << "Unable to convert '" << value
00057 << "' from Unicode to MultiByte form.\n";
00058 return false;
00059 }
00060
00061 char *mb_result = (char *)alloca(mb_result_len);
00062 WideCharToMultiByte(CP_ACP, 0,
00063 wvalue.data(), wvalue.length(),
00064 mb_result, mb_result_len,
00065 NULL, NULL);
00066
00067 if (express_cat.is_debug()) {
00068 express_cat.debug()
00069 << "Converted '" << value << "' to '" << mb_result
00070 << "' for storing in registry.\n";
00071 }
00072
00073 return do_set(key, name, REG_SZ, mb_result, mb_result_len, rl);
00074 }
00075
00076
00077
00078
00079
00080
00081
00082
00083 bool WindowsRegistry::
00084 set_int_value(const string &key, const string &name, int value,
00085 WindowsRegistry::RegLevel rl)
00086 {
00087 DWORD dw = value;
00088 return do_set(key, name, REG_DWORD, &dw, sizeof(dw), rl);
00089 }
00090
00091
00092
00093
00094
00095
00096
00097 WindowsRegistry::Type WindowsRegistry::
00098 get_key_type(const string &key, const string &name,
00099 WindowsRegistry::RegLevel rl)
00100 {
00101 int data_type;
00102 string data;
00103 if (!do_get(key, name, data_type, data, rl)) {
00104 return T_none;
00105 }
00106
00107 switch (data_type) {
00108 case REG_SZ:
00109 return T_string;
00110
00111 case REG_DWORD:
00112 return T_int;
00113
00114 default:
00115 return T_none;
00116 }
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 string WindowsRegistry::
00130 get_string_value(const string &key, const string &name,
00131 const string &default_value,
00132 WindowsRegistry::RegLevel rl)
00133 {
00134 int data_type;
00135 string data;
00136 if (!do_get(key, name, data_type, data, rl)) {
00137 return default_value;
00138 }
00139
00140 if (data_type != REG_SZ) {
00141 express_cat.warning()
00142 << "Registry key " << key << " does not contain a string value.\n";
00143 return default_value;
00144 }
00145
00146
00147
00148
00149 if (data.empty()) {
00150 return data;
00151 }
00152
00153 int wide_result_len =
00154 MultiByteToWideChar(CP_ACP, 0,
00155 data.data(), data.length(),
00156 NULL, 0);
00157 if (wide_result_len == 0) {
00158 express_cat.error()
00159 << "Unable to convert '" << data
00160 << "' from MultiByte to Unicode form.\n";
00161 return data;
00162 }
00163
00164 wchar_t *wide_result = (wchar_t *)alloca(wide_result_len * sizeof(wchar_t));
00165 MultiByteToWideChar(CP_ACP, 0,
00166 data.data(), data.length(),
00167 wide_result, wide_result_len);
00168
00169 wstring wdata(wide_result, wide_result_len);
00170
00171 TextEncoder encoder;
00172 string result = encoder.encode_wtext(wdata);
00173
00174 if (express_cat.is_debug()) {
00175 express_cat.debug()
00176 << "Converted '" << data << "' from registry to '" << result << "'\n";
00177 }
00178
00179 return result;
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 int WindowsRegistry::
00191 get_int_value(const string &key, const string &name, int default_value,
00192 WindowsRegistry::RegLevel rl)
00193 {
00194 int data_type;
00195 string data;
00196 if (!do_get(key, name, data_type, data, rl)) {
00197 return default_value;
00198 }
00199
00200 if (data_type != REG_DWORD) {
00201 express_cat.warning()
00202 << "Registry key " << key << " does not contain an integer value.\n";
00203 return default_value;
00204 }
00205
00206
00207 nassertr(data.length() == sizeof(DWORD), default_value);
00208 DWORD dw = *(DWORD *)data.data();
00209 return dw;
00210 }
00211
00212
00213
00214
00215
00216
00217
00218 bool WindowsRegistry::
00219 do_set(const string &key, const string &name,
00220 int data_type, const void *data, int data_length,
00221 const WindowsRegistry::RegLevel rl)
00222 {
00223 HKEY hkey, regkey = HKEY_LOCAL_MACHINE;
00224 LONG error;
00225
00226 if (rl == rl_user)
00227 regkey = HKEY_CURRENT_USER;
00228
00229 error =
00230 RegOpenKeyEx(regkey, key.c_str(), 0, KEY_SET_VALUE, &hkey);
00231 if (error != ERROR_SUCCESS) {
00232 express_cat.error()
00233 << "Unable to open registry key " << key
00234 << ": " << format_message(error) << "\n";
00235 return false;
00236 }
00237
00238 bool okflag = true;
00239
00240 error =
00241 RegSetValueEx(hkey, name.c_str(), 0, data_type,
00242 (CONST BYTE *)data, data_length);
00243 if (error != ERROR_SUCCESS) {
00244 express_cat.error()
00245 << "Unable to set registry key " << key << " name " << name
00246 << ": " << format_message(error) << "\n";
00247 okflag = false;
00248 }
00249
00250 error = RegCloseKey(hkey);
00251 if (error != ERROR_SUCCESS) {
00252 express_cat.warning()
00253 << "Unable to close opened registry key " << key
00254 << ": " << format_message(error) << "\n";
00255 }
00256
00257 return okflag;
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267 bool WindowsRegistry::
00268 do_get(const string &key, const string &name, int &data_type, string &data,
00269 const WindowsRegistry::RegLevel rl)
00270 {
00271 HKEY hkey, regkey = HKEY_LOCAL_MACHINE;
00272 LONG error;
00273
00274 if (rl == rl_user)
00275 regkey = HKEY_CURRENT_USER;
00276
00277 error =
00278 RegOpenKeyEx(regkey, key.c_str(), 0, KEY_QUERY_VALUE, &hkey);
00279 if (error != ERROR_SUCCESS) {
00280 express_cat.debug()
00281 << "Unable to open registry key " << key
00282 << ": " << format_message(error) << "\n";
00283 return false;
00284 }
00285
00286 bool okflag = true;
00287
00288
00289
00290 static const size_t init_buffer_size = 1024;
00291 char init_buffer[init_buffer_size];
00292 DWORD buffer_size = init_buffer_size;
00293 DWORD dw_data_type;
00294
00295 error =
00296 RegQueryValueEx(hkey, name.c_str(), 0, &dw_data_type,
00297 (BYTE *)init_buffer, &buffer_size);
00298 if (error == ERROR_SUCCESS) {
00299 data_type = dw_data_type;
00300 if (data_type == REG_SZ ||
00301 data_type == REG_MULTI_SZ ||
00302 data_type == REG_EXPAND_SZ) {
00303
00304 if (buffer_size > 0)
00305 buffer_size--;
00306 }
00307 data = string(init_buffer, buffer_size);
00308
00309 } else if (error == ERROR_MORE_DATA) {
00310
00311
00312
00313
00314
00315
00316 char *new_buffer = (char *)PANDA_MALLOC_ARRAY(buffer_size);
00317 error =
00318 RegQueryValueEx(hkey, name.c_str(), 0, &dw_data_type,
00319 (BYTE *)new_buffer, &buffer_size);
00320 if (error == ERROR_SUCCESS) {
00321 data_type = dw_data_type;
00322 if (data_type == REG_SZ ||
00323 data_type == REG_MULTI_SZ ||
00324 data_type == REG_EXPAND_SZ) {
00325
00326 if (buffer_size > 0)
00327 buffer_size--;
00328 }
00329 data = string(new_buffer, buffer_size);
00330 }
00331 PANDA_FREE_ARRAY(new_buffer);
00332 }
00333
00334 if (error != ERROR_SUCCESS) {
00335 express_cat.debug()
00336 << "Unable to get registry value " << name
00337 << ": " << format_message(error) << "\n";
00338 okflag = false;
00339 }
00340
00341 error = RegCloseKey(hkey);
00342 if (error != ERROR_SUCCESS) {
00343 express_cat.warning()
00344 << "Unable to close opened registry key " << key
00345 << ": " << format_message(error) << "\n";
00346 }
00347
00348 if (okflag) {
00349 if (data_type == REG_EXPAND_SZ) {
00350
00351 DWORD destSize=ExpandEnvironmentStrings(data.c_str(), 0, 0);
00352 char *dest = (char *)PANDA_MALLOC_ARRAY(destSize);
00353 ExpandEnvironmentStrings(data.c_str(), dest, destSize);
00354 data = dest;
00355 PANDA_FREE_ARRAY(dest);
00356 data_type = REG_SZ;
00357 }
00358 }
00359
00360 return okflag;
00361 }
00362
00363
00364
00365
00366
00367
00368
00369 string WindowsRegistry::
00370 format_message(int error_code) {
00371 PVOID buffer;
00372 DWORD length =
00373 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
00374 NULL, error_code, 0, (LPTSTR)&buffer, 0, NULL);
00375 if (length == 0) {
00376 return "Unknown error message";
00377 }
00378
00379 const char *text = (const char *)buffer;
00380
00381
00382 while (length > 0 &&
00383 (text[length - 1] == '\r' || text[length - 1] == '\n')) {
00384 length--;
00385 }
00386
00387 string result((const char *)text, length);
00388 LocalFree(buffer);
00389 return result;
00390 }
00391
00392 #endif
00393
00394
00395