Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: src/shared/Utils.cpp

Issue 11254007: Installation with registry keys
Patch Set: Created July 25, 2013, 9:57 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/shared/Utils.h ('k') | test/DictionaryTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/shared/Utils.cpp
===================================================================
--- a/src/shared/Utils.cpp
+++ b/src/shared/Utils.cpp
@@ -9,11 +9,7 @@
namespace
{
- // See http://blogs.msdn.com/b/oldnewthing/archive/2004/10/25/247180.aspx
- EXTERN_C IMAGE_DOS_HEADER __ImageBase;
-
std::wstring appDataPath;
-
}
bool IsWindowsVistaOrLater()
@@ -55,35 +51,6 @@
return utf16String;
}
-std::wstring GetDllDir()
-{
- std::vector<WCHAR> path(MAX_PATH);
- DWORD length = GetModuleFileNameW((HINSTANCE)&__ImageBase, &path[0], path.size());
-
- while (length == path.size())
- {
- // Buffer too small, double buffer size
- path.resize(path.size() * 2);
- length = GetModuleFileNameW((HINSTANCE)&__ImageBase, &path[0], path.size());
- }
-
- try
- {
- if (length == 0)
- throw std::runtime_error("Failed determining module path");
-
- std::vector<WCHAR>::reverse_iterator it = std::find(path.rbegin(), path.rend(), L'\\');
- if (it == path.rend())
- throw std::runtime_error("Unexpected plugin path, no backslash found");
-
- return std::wstring(path.begin(), it.base());
- }
- catch (const std::exception&)
- {
- return std::wstring();
- }
-}
-
std::wstring GetAppDataPath()
{
if (appDataPath.empty())
@@ -110,3 +77,154 @@
}
return appDataPath;
}
+
+/**
+ * Configuration Key
+ *
+ * The configuration key is found in [hive]\Software\Adblock Pluse for IE, where [hive] is either HKCU or HKLM.
+ * An HKCU key overrides any found in HKLM, which mirrors the behavior of the COM subsystem when loading by CLSID.
+ * Also in parallel, the HKCU key is used by the developer install; the HKLM one used in the MSI.
+ */
+class Config_Key {
+public:
+ Config_Key();
+ ~Config_Key();
+
+ std::wstring value_wstring( std::wstring name );
+
+private:
+ /**
+ * Invariant: Not null.
+ */
+ HKEY handle;
+
+ static const std::wstring keyname;
+};
+
+const std::wstring Config_Key::keyname = L"Software\\Adblock Plus for IE";
+
+Config_Key::Config_Key()
+{
+ HKEY h;
+ LONG hr;
+ hr = RegOpenKeyEx( HKEY_CURRENT_USER, keyname.c_str(), 0, KEY_QUERY_VALUE, &h );
+ if ( hr != ERROR_SUCCESS ) {
+ // Assert key not found in the HKCU
+ // Try again in HKLM
+ hr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, keyname.c_str(), 0, KEY_QUERY_VALUE, &h );
+ if ( hr != ERROR_SUCCESS ) {
+ // Assert key not found in either HKCU or HKLM
+ // Now we give up.
+ throw std::runtime_error( "Could not open configuration registry key" );
+ }
+ }
+ // Assert one of the RegOpenKeyEx calls succeeded.
+ if ( h == 0 ) {
+ // Success and a null handle?
+ throw std::runtime_error( "Opened registry key but received null handle" );
+ }
+ handle = h;
+}
+
+Config_Key::~Config_Key()
+{
+ RegCloseKey( handle );
+}
+
+/**
+ * Retrieve a Unicode string value from this registry key.
+ *
+ * Reading string values is significantly more complicated than reading simpler, fixed-size types. There are memory allocation issues to get
+ * right, which necessitates two queries. There's also a peculiarity with extra null termination characters.
+ *
+ * Note: The Windows registry only has partial type support for strings. The string type "REG_SZ" does not say anything about string encoding,
+ * only that it's a zero-terminated C-style string. It doesn't say anything about the encoding of the string. We check that the value has the
+ * the type REG_SZ, but that's not completely reliable.
+ *
+ * Precondition:
+ * sizeof( wchar_t ) == 2
+ */
+std::wstring
+Config_Key::value_wstring( std::wstring name )
+{
+ DWORD type;
+ DWORD size = 0;
+ /*
+ * Step one is to determine the presence of the value, along with its type and size.
+ * Note that the size is given in bytes, not in characters.
+ */
+ DWORD hr = ::RegQueryValueEx( handle, name.c_str(), 0, &type, 0, &size );
+ if ( hr != ERROR_SUCCESS ) {
+ throw std::runtime_error( "Error finding registry value" );
+ }
+ if ( type != REG_SZ ) {
+ throw std::runtime_error( "Registry value does not have string type" );
+ }
+
+ /*
+ * Step two is to allocate a buffer for the string and query for its value.
+ */
+ // Round the size up to the nearest multiple of two.
+ size = ( size + 1 ) & ~ DWORD(1);
+ size_t psize = size >> 1;
+ std::unique_ptr< wchar_t[] > p( new wchar_t[ psize ] );
+ /*
+ * We're relying that the internal representation of a string is a wchar_t array, which is true for Microsoft compilers.
+ * This is fine, since we're already Microsoft-specific with the system call.
+ * It would be better if Microsoft were to write type-safe C++ wrappers for these system calls, but that seems unlikely.
+ */
+ hr = RegQueryValueEx( handle, name.c_str(), 0, 0, reinterpret_cast<BYTE *>( p.get() ), &size );
+ if ( hr != ERROR_SUCCESS ) {
+ throw std::runtime_error( "Error retrieving registry value" );
+ }
+
+ /*
+ * Step three is to construct a return string.
+ *
+ * There's the possibility of an extra terminating null character in the return value of the query.
+ * If so, we have to decrement the length of the return value to eliminate it.
+ * If it persists, it will interfere with later string operations such as concatenation.
+ */
+ if ( p[ psize - 1 ] == L'\0' ) --psize;
+ return std::wstring( p.get(), psize );
+}
+
+bool
+Location::all_known()
+{
+ // Not optimized at all. No need--it's only executed once, at DLL startup.
+ try {
+ /*
+ * If any of these functions throw, we report an error.
+ */
+ Config_Key ck;
+ (void) ck.value_wstring( L"engine" );
+ (void) ck.value_wstring( L"locales_dir" );
+ (void) ck.value_wstring( L"html_dir" );
+ } catch ( ... ) {
+ // Ignore any specific error.
+ return false;
+ }
+ return true;
+}
+
+std::wstring
+Location::engine()
+{
+ Config_Key ck;
+ return ck.value_wstring( L"engine" );
+}
+
+std::wstring
+Location::locales_dir()
+{
+ Config_Key ck;
+ return ck.value_wstring( L"locales_dir" );
+}
+
+std::wstring
+Location::html_dir()
+{
+ Config_Key ck;
+ return ck.value_wstring( L"html_dir" );
+}
« no previous file with comments | « src/shared/Utils.h ('k') | test/DictionaryTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld