Browse Source

new WindowsRegistry class

David Rose 23 years ago
parent
commit
e3a40daa0e

+ 3 - 0
panda/src/express/Sources.pp

@@ -66,6 +66,7 @@
     virtualFileMountMultifile.I virtualFileMountSystem.h \
     virtualFileMountMultifile.I virtualFileMountSystem.h \
     virtualFileMountSystem.I virtualFileSimple.h virtualFileSimple.I \
     virtualFileMountSystem.I virtualFileSimple.h virtualFileSimple.I \
     virtualFileSystem.h virtualFileSystem.I \
     virtualFileSystem.h virtualFileSystem.I \
+    windowsRegistry.h \
     zStream.I zStream.h zStreamBuf.h \
     zStream.I zStream.h zStreamBuf.h \
     $[if $[HAVE_CRYPTO], \
     $[if $[HAVE_CRYPTO], \
        crypto_utils.cxx crypto_utils.h patchfile.I \
        crypto_utils.cxx crypto_utils.h patchfile.I \
@@ -103,6 +104,7 @@
     virtualFileMount.cxx \
     virtualFileMount.cxx \
     virtualFileMountMultifile.cxx virtualFileMountSystem.cxx \
     virtualFileMountMultifile.cxx virtualFileMountSystem.cxx \
     virtualFileSimple.cxx virtualFileSystem.cxx \
     virtualFileSimple.cxx virtualFileSystem.cxx \
+    windowsRegistry.cxx \
     zStream.cxx zStreamBuf.cxx
     zStream.cxx zStreamBuf.cxx
 
 
   #define INSTALL_HEADERS  \
   #define INSTALL_HEADERS  \
@@ -158,6 +160,7 @@
     virtualFileMountMultifile.I virtualFileMountSystem.h \
     virtualFileMountMultifile.I virtualFileMountSystem.h \
     virtualFileMountSystem.I virtualFileSimple.h virtualFileSimple.I \
     virtualFileMountSystem.I virtualFileSimple.h virtualFileSimple.I \
     virtualFileSystem.h virtualFileSystem.I \
     virtualFileSystem.h virtualFileSystem.I \
+    windowsRegistry.h \
     zStream.I zStream.h zStreamBuf.h
     zStream.I zStream.h zStreamBuf.h
 
 
   #define IGATESCAN all
   #define IGATESCAN all

+ 1 - 0
panda/src/express/express_composite2.cxx

@@ -25,6 +25,7 @@
 #include "virtualFileMountSystem.cxx"
 #include "virtualFileMountSystem.cxx"
 #include "virtualFileSimple.cxx"
 #include "virtualFileSimple.cxx"
 #include "virtualFileSystem.cxx"
 #include "virtualFileSystem.cxx"
+#include "windowsRegistry.cxx"
 #include "zStream.cxx"
 #include "zStream.cxx"
 #include "zStreamBuf.cxx"
 #include "zStreamBuf.cxx"
 
 

+ 302 - 0
panda/src/express/windowsRegistry.cxx

@@ -0,0 +1,302 @@
+// Filename: windowsRegistry.cxx
+// Created by:  drose (06Aug01)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "windowsRegistry.h"
+#include "config_express.h"
+
+#ifdef WIN32_VC
+
+#include <windows.h>
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsRegistry::set_string_value
+//       Access: Published, Static
+//  Description: Sets the registry key to the indicated value as a
+//               string.  The supplied string value is automatically
+//               converted from whatever encoding is set by
+//               TextEncoder::set_default_encoding() and written as a
+//               Unicode string.  The registry key must already exist
+//               prior to calling this function.
+////////////////////////////////////////////////////////////////////
+bool WindowsRegistry::
+set_string_value(const string &key, const string &name, const string &value) {
+  TextEncoder encoder;
+  wstring wvalue = encoder.decode_text(value);
+
+  return do_set(key, name, REG_SZ, wvalue.data(),
+                wvalue.length() * sizeof(wchar_t));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsRegistry::set_int_value
+//       Access: Published, Static
+//  Description: Sets the registry key to the indicated value as an
+//               integer.  The registry key must already exist prior
+//               to calling this function.
+////////////////////////////////////////////////////////////////////
+bool WindowsRegistry::
+set_int_value(const string &key, const string &name, int value) {
+  DWORD dw = value;
+  return do_set(key, name, REG_DWORD, &dw, sizeof(dw));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsRegistry::get_key_type
+//       Access: Published, Static
+//  Description: Returns the type of the indicated key, or T_none if
+//               the key is not known or is some unsupported type.
+////////////////////////////////////////////////////////////////////
+WindowsRegistry::Type WindowsRegistry::
+get_key_type(const string &key, const string &name) {
+  int data_type;
+  string data;
+  if (!do_get(key, name, data_type, data)) {
+    return T_none;
+  }
+
+  switch (data_type) {
+  case REG_SZ:
+    return T_string;
+
+  case REG_DWORD:
+    return T_int;
+
+  default:
+    return T_none;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsRegistry::get_string_value
+//       Access: Published, Static
+//  Description: Returns the value associated with the indicated
+//               registry key, assuming it is a string value.  The
+//               string value is automatically encoded using
+//               TextEncoder::get_default_encoding().  If the key is
+//               not defined or is not a string type value,
+//               default_value is returned instead.
+////////////////////////////////////////////////////////////////////
+string WindowsRegistry::
+get_string_value(const string &key, const string &name,
+                 const string &default_value) {
+  int data_type;
+  string data;
+  if (!do_get(key, name, data_type, data)) {
+    return default_value;
+  }
+
+  if (data_type != REG_SZ) {
+    express_cat.warning()
+      << "Registry key " << key << " does not contain a string value.\n";
+    return default_value;
+  }
+
+  // Now we have a Unicode string stored in a string buffer.  Lame.
+  wstring wdata((wchar_t *)data.data(), (data.length() / sizeof(wchar_t)));
+
+  TextEncoder encoder;
+  return encoder.encode_wtext(wdata);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsRegistry::get_int_value
+//       Access: Published, Static
+//  Description: Returns the value associated with the indicated
+//               registry key, assuming it is an integer value.  If
+//               the key is not defined or is not an integer type
+//               value, default_value is returned instead.
+////////////////////////////////////////////////////////////////////
+int WindowsRegistry::
+get_int_value(const string &key, const string &name, int default_value) {
+  int data_type;
+  string data;
+  if (!do_get(key, name, data_type, data)) {
+    return default_value;
+  }
+
+  if (data_type != REG_DWORD) {
+    express_cat.warning()
+      << "Registry key " << key << " does not contain an integer value.\n";
+    return default_value;
+  }
+  
+  // Now we have a DWORD encoded in a string.
+  nassertr(data.length() == sizeof(DWORD), default_value);
+  DWORD dw = *(DWORD *)data.data();
+  return dw;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsRegistry::do_set
+//       Access: Private, Static
+//  Description: The internal function to actually make all of the
+//               appropriate windows calls to set the registry value.
+////////////////////////////////////////////////////////////////////
+bool WindowsRegistry::
+do_set(const string &key, const string &name,
+       int data_type, const void *data, int data_length) {
+  HKEY hkey;
+  LONG error;
+
+  error =
+    RegOpenKeyEx(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_SET_VALUE, &hkey);
+  if (error != ERROR_SUCCESS) {
+    express_cat.error()
+      << "Unable to open registry key " << key
+      << ": " << format_message(error) << "\n";
+    return false;
+  }
+
+  TextEncoder encoder;
+  wstring wname = encoder.decode_text(name);
+
+  bool okflag = true;
+
+  // It's possible that making this direct call to RegSetValueExW()
+  // will cause this dll not to load on Win95.  It's difficult to test
+  // this hypothesis without having a Win95 machine available.  But
+  // since we're not officially supporting Win95 anymore, maybe I
+  // shouldn't even care.
+  error =
+    RegSetValueExW(hkey, wname.c_str(), 0, data_type, 
+                   (CONST BYTE *)data, data_length);
+  if (error != ERROR_SUCCESS) {
+    express_cat.error()
+      << "Unable to set registry key " << key << " name " << name 
+      << ": " << format_message(error) << "\n";
+    okflag = false;
+  }
+
+  error = RegCloseKey(hkey);
+  if (error != ERROR_SUCCESS) {
+    express_cat.warning()
+      << "Unable to close opened registry key " << key
+      << ": " << format_message(error) << "\n";
+  }
+
+  return okflag;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsRegistry::do_get
+//       Access: Private, Static
+//  Description: The internal function to actually make all of the
+//               appropriate windows calls to retrieve the registry
+//               value.
+////////////////////////////////////////////////////////////////////
+bool WindowsRegistry::
+do_get(const string &key, const string &name, int &data_type, string &data) {
+  HKEY hkey;
+  LONG error;
+
+  error =
+    RegOpenKeyEx(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_QUERY_VALUE, &hkey);
+  if (error != ERROR_SUCCESS) {
+    express_cat.error()
+      << "Unable to open registry key " << key
+      << ": " << format_message(error) << "\n";
+    return false;
+  }
+
+  TextEncoder encoder;
+  wstring wname = encoder.decode_text(name);
+
+  bool okflag = true;
+
+  // We start with a 1K buffer; presumably that will be big enough
+  // most of the time.
+  static const size_t init_buffer_size = 1024;
+  char init_buffer[init_buffer_size];
+  DWORD buffer_size = init_buffer_size;
+  DWORD dw_data_type;
+
+  error =
+    RegQueryValueExW(hkey, wname.c_str(), 0, &dw_data_type, 
+                     (BYTE *)init_buffer, &buffer_size);
+  if (error == ERROR_SUCCESS) {
+    data_type = dw_data_type;
+    if (data_type == REG_SZ || 
+        data_type == REG_MULTI_SZ || 
+        data_type == REG_EXPAND_SZ) {
+      // Eliminate the trailing null character.
+      buffer_size--;
+    }
+    data = string(init_buffer, buffer_size);
+
+  } else if (error == ERROR_MORE_DATA) {
+    // Huh, 1K wasn't big enough.  Ok, get a bigger buffer.
+
+    // If we were querying HKEY_PERFORMANCE_DATA, we'd have to keep
+    // guessing bigger and bigger until we got it.  Since we're
+    // querying static data for now, we can just use the size Windows
+    // tells us.
+    char *new_buffer = new char[buffer_size];
+    error =
+      RegQueryValueExW(hkey, wname.c_str(), 0, &dw_data_type, 
+                       (BYTE *)new_buffer, &buffer_size);
+    if (error == ERROR_SUCCESS) {
+      data_type = dw_data_type;
+      if (data_type == REG_SZ || 
+          data_type == REG_MULTI_SZ || 
+          data_type == REG_EXPAND_SZ) {
+        // Eliminate the trailing null character.
+        buffer_size--;
+      }
+      data = string(new_buffer, buffer_size);
+    }
+    delete new_buffer;
+  }
+
+  if (error != ERROR_SUCCESS) {
+    express_cat.error()
+      << "Unable to get registry key " << key << " name " << name 
+      << ": " << format_message(error) << "\n";
+    okflag = false;
+  }
+
+  error = RegCloseKey(hkey);
+  if (error != ERROR_SUCCESS) {
+    express_cat.warning()
+      << "Unable to close opened registry key " << key
+      << ": " << format_message(error) << "\n";
+  }
+
+  return okflag;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsRegistry::format_message
+//       Access: Private, Static
+//  Description: Returns the Windows error message associated with the
+//               given error code.
+////////////////////////////////////////////////////////////////////
+string WindowsRegistry::
+format_message(int error_code) {
+  PVOID buffer;
+  DWORD length = 
+    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+                  NULL, error_code, 0, (LPTSTR)&buffer, 0, NULL);
+  if (length == 0) {
+    return "Unknown error message";
+  }
+  string result((const char *)buffer, length);
+  LocalFree(buffer);
+  return result;
+}
+
+#endif  // WIN32_VC

+ 62 - 0
panda/src/express/windowsRegistry.h

@@ -0,0 +1,62 @@
+// Filename: windowsRegistry.h
+// Created by:  drose (06Aug01)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef WINDOWSREGISTRY_H
+#define WINDOWSREGISTRY_H
+
+#include "pandabase.h"
+
+// This class is only defined on Windows builds.
+#ifdef WIN32_VC
+
+////////////////////////////////////////////////////////////////////
+//       Class : WindowsRegistry
+// Description : This class provides a hook to Python to read and
+//               write strings and integers to the windows registry.
+//               It automatically converts strings from utf-8 encoding
+//               and stores them in Unicode (and conversely reconverts
+//               them on retrieval).
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDAEXPRESS WindowsRegistry {
+PUBLISHED:
+  static bool set_string_value(const string &key, const string &name,
+                               const string &value);
+  static bool set_int_value(const string &key, const string &name, int value);
+
+  enum Type {
+    T_none,
+    T_int,
+    T_string,
+  };
+  static Type get_key_type(const string &key, const string &name);
+  static string get_string_value(const string &key, const string &name,
+                                 const string &default_value);
+  static int get_int_value(const string &key, const string &name,
+                           int default_value);
+
+private:
+  static bool do_set(const string &key, const string &name,
+                     int data_type, const void *data, int data_length);
+  static bool do_get(const string &key, const string &name,
+                     int &data_type, string &data);
+  static string format_message(int error_code);
+};
+
+#endif  // WIN32_VC
+
+#endif