diff --git a/stepmania/src/StepMania.vcproj b/stepmania/src/StepMania.vcproj
index 6148e8a960..cb6ba378a0 100644
--- a/stepmania/src/StepMania.vcproj
+++ b/stepmania/src/StepMania.vcproj
@@ -1159,6 +1159,12 @@ cl /Zl /nologo /c verstub.cpp /Fo"$(IntDir)"\
+
+
+
+
diff --git a/stepmania/src/archutils/Win32/RegistryAccess.cpp b/stepmania/src/archutils/Win32/RegistryAccess.cpp
new file mode 100644
index 0000000000..cd3411620e
--- /dev/null
+++ b/stepmania/src/archutils/Win32/RegistryAccess.cpp
@@ -0,0 +1,140 @@
+#include "global.h"
+#include "RegistryAccess.h"
+#include "RageLog.h"
+#include "RageUtil.h"
+
+/* Given "HKEY_LOCAL_MACHINE\hardware\foo", return "hardware\foo", and place
+ * the HKEY_LOCAL_MACHINE constant in key. */
+static bool GetRegKeyType( const CString &in, CString &out, HKEY &key )
+{
+ unsigned backslash = in.find( '\\' );
+ if( backslash == in.npos )
+ {
+ LOG->Warn( "Invalid registry key: \"%s\" ", in.c_str() );
+ return false;
+ }
+
+ CString type = in.substr( 0, backslash );
+
+ if( !type.CompareNoCase( "HKEY_CLASSES_ROOT" ) ) key = HKEY_CLASSES_ROOT;
+ else if( !type.CompareNoCase( "HKEY_CURRENT_CONFIG" ) ) key = HKEY_CURRENT_CONFIG;
+ else if( !type.CompareNoCase( "HKEY_CURRENT_USER" ) ) key = HKEY_CURRENT_USER;
+ else if( !type.CompareNoCase( "HKEY_LOCAL_MACHINE" ) ) key = HKEY_LOCAL_MACHINE;
+ else if( !type.CompareNoCase( "HKEY_USERS" ) ) key = HKEY_USERS;
+ else
+ {
+ LOG->Warn( "Invalid registry key: \"%s\" ", in.c_str() );
+ return false;
+ }
+
+ out = in.substr( backslash+1 );
+
+ return true;
+}
+
+/* Given a full key, eg. "HKEY_LOCAL_MACHINE\hardware\foo", open it and return it.
+ * On error, return NULL. */
+static HKEY OpenRegKey( const CString &key )
+{
+ CString subkey;
+ HKEY type;
+ if( !GetRegKeyType( key, subkey, type ) )
+ return NULL;
+
+ HKEY retkey;
+ LONG retval = RegOpenKeyEx( type, subkey, 0, KEY_READ, &retkey );
+ if ( retval != ERROR_SUCCESS )
+ {
+ LOG->Warn( werr_ssprintf(retval, "RegOpenKeyEx(%i,%s) error", type, subkey.c_str()) );
+ return NULL;
+ }
+
+ return retkey;
+}
+
+bool GetRegValue( const CString &key, const CString &sName, CString &val )
+{
+ HKEY hkey = OpenRegKey( key );
+ if( hkey == NULL )
+ return false;
+
+ char sBuffer[MAX_PATH];
+ DWORD nSize = sizeof(sBuffer);
+ DWORD Type;
+ LONG ret = RegQueryValueEx( hkey, sName, NULL, &Type, (LPBYTE)sBuffer, &nSize );
+ RegCloseKey( hkey );
+ if( ret != ERROR_SUCCESS )
+ return false;
+
+ /* Actually, CStrings are 8-bit clean, so we can accept any type of data. Remove
+ * this if that becomes useful. */
+ if( Type != REG_SZ && Type != REG_MULTI_SZ && Type != REG_EXPAND_SZ && Type != REG_BINARY )
+ return false; /* type mismatch */
+
+ if( nSize && (Type == REG_SZ || Type == REG_MULTI_SZ || Type == REG_EXPAND_SZ) )
+ --nSize; /* remove nul terminator */
+
+ val = CString( sBuffer, nSize );
+ return true;
+}
+
+bool GetRegValue( const CString &key, CString sName, int &val )
+{
+ HKEY hkey = OpenRegKey( key );
+ if( hkey == NULL )
+ return false;
+
+ DWORD value;
+ DWORD nSize = sizeof(value);
+ DWORD Type;
+ LONG ret = RegQueryValueEx( hkey, sName, NULL, &Type, (LPBYTE) &value, &nSize );
+ RegCloseKey( hkey );
+ if( ret != ERROR_SUCCESS )
+ return false;
+
+ if( Type != REG_DWORD )
+ return false; /* type mismatch */
+
+ val = value;
+ return true;
+}
+
+bool GetRegSubKeys( const CString &key, vector &lst, const CString ®ex, bool bReturnPathToo )
+{
+ HKEY hkey = OpenRegKey( key );
+ if ( hkey == NULL )
+ return false;
+
+ Regex re(regex);
+
+ bool bError = false;
+ for( int index = 0; ; ++index )
+ {
+ FILETIME ft;
+ char szBuffer[MAX_PATH];
+ DWORD nSize = sizeof(szBuffer);
+ LONG ret = RegEnumKeyEx( hkey, index, szBuffer, &nSize, NULL, NULL, NULL, &ft);
+ if( ret == ERROR_NO_MORE_ITEMS )
+ break;
+
+ if( ret != ERROR_SUCCESS )
+ {
+ LOG->Warn( werr_ssprintf(ret, "GetRegSubKeys(%p,%i) error", hkey, index) );
+ bError = true;
+ break;
+ }
+
+ CString str( szBuffer, nSize );
+
+ if( re.Compare(str) )
+ {
+ if( bReturnPathToo )
+ str = key + "\\" + str;
+ lst.push_back( str );
+ }
+ }
+
+ RegCloseKey( hkey );
+
+ return !bError;
+}
diff --git a/stepmania/src/archutils/Win32/RegistryAccess.h b/stepmania/src/archutils/Win32/RegistryAccess.h
new file mode 100644
index 0000000000..c3bc97356c
--- /dev/null
+++ b/stepmania/src/archutils/Win32/RegistryAccess.h
@@ -0,0 +1,9 @@
+#ifndef REGISTRY_ACCESS_H
+#define REGISTRY_ACCESS_H
+
+#include "windows.h"
+bool GetRegValue( const CString &key, const CString &sName, CString &val );
+bool GetRegValue( const CString &key, CString sName, int &val );
+bool GetRegSubKeys( const CString &key, vector &lst, const CString ®ex = ".*", bool bReturnPathToo = true );
+
+#endif