[PATCH v4 1/7] kernel32: Implement registry mapping in GetPrivateProfileStringW().
Zebediah Figura
z.figura12 at gmail.com
Sun Jul 12 20:06:44 CDT 2020
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=4096
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
dlls/kernel32/profile.c | 170 +++++++++++++++++++++++++++++++++++++---
1 file changed, 160 insertions(+), 10 deletions(-)
diff --git a/dlls/kernel32/profile.c b/dlls/kernel32/profile.c
index 2cf0819023d..3e06543a660 100644
--- a/dlls/kernel32/profile.c
+++ b/dlls/kernel32/profile.c
@@ -29,7 +29,9 @@
#include "winbase.h"
#include "winnls.h"
#include "winerror.h"
+#include "winreg.h"
#include "winternl.h"
+#include "shlwapi.h"
#include "wine/unicode.h"
#include "wine/library.h"
#include "wine/debug.h"
@@ -1016,6 +1018,129 @@ static BOOL PROFILE_SetString( LPCWSTR section_name, LPCWSTR key_name,
return TRUE;
}
+static HKEY open_file_mapping_key( const WCHAR *filename )
+{
+ static const WCHAR mapping_pathW[] = {'S','o','f','t','w','a','r','e',
+ '\\','M','i','c','r','o','s','o','f','t',
+ '\\','W','i','n','d','o','w','s',' ','N','T',
+ '\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n',
+ '\\','I','n','i','F','i','l','e','M','a','p','p','i','n','g',0};
+ static HKEY mapping_key;
+ HKEY key;
+
+ EnterCriticalSection( &PROFILE_CritSect );
+
+ if (!mapping_key && RegOpenKeyExW( HKEY_LOCAL_MACHINE, mapping_pathW, 0, KEY_WOW64_64KEY, &mapping_key ))
+ mapping_key = NULL;
+
+ LeaveCriticalSection( &PROFILE_CritSect );
+
+ if (mapping_key && !RegOpenKeyExW( mapping_key, PathFindFileNameW( filename ), 0, KEY_READ, &key ))
+ return key;
+ return NULL;
+}
+
+static WCHAR *get_key_value( HKEY key, const WCHAR *value )
+{
+ DWORD size = 0;
+ WCHAR *data;
+
+ if (RegGetValueW( key, NULL, value, RRF_RT_REG_SZ | RRF_NOEXPAND, NULL, NULL, &size )) return NULL;
+ if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL;
+ if (!RegGetValueW( key, NULL, value, RRF_RT_REG_SZ | RRF_NOEXPAND, NULL, (BYTE *)data, &size )) return data;
+ HeapFree( GetProcessHeap(), 0, data );
+ return NULL;
+}
+
+static HKEY open_mapped_key( const WCHAR *path, BOOL write )
+{
+ static const WCHAR softwareW[] = {'S','o','f','t','w','a','r','e','\\',0};
+ static const WCHAR usrW[] = {'U','S','R',':'};
+ static const WCHAR sysW[] = {'S','Y','S',':'};
+ WCHAR *combined_path;
+ const WCHAR *p;
+ LSTATUS res;
+ HKEY key;
+
+ TRACE("%s\n", debugstr_w( path ));
+
+ for (p = path; strchr("!#@", *p); p++)
+ FIXME("ignoring %c modifier\n", *p);
+
+ if (!strncmpW( p, usrW, ARRAY_SIZE( usrW ) ))
+ {
+ if (write)
+ res = RegCreateKeyExW( HKEY_CURRENT_USER, p + 4, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &key, NULL );
+ else
+ res = RegOpenKeyExW( HKEY_CURRENT_USER, p + 4, 0, KEY_READ, &key );
+ return res ? NULL : key;
+ }
+
+ if (!strncmpW( p, sysW, ARRAY_SIZE( sysW ) ))
+ {
+ p += 4;
+ if (!(combined_path = HeapAlloc( GetProcessHeap(), 0,
+ (ARRAY_SIZE( softwareW ) + strlenW( p )) * sizeof(WCHAR) )))
+ return NULL;
+ strcpyW( combined_path, softwareW );
+ strcatW( combined_path, p );
+ if (write)
+ res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, combined_path, 0, NULL,
+ 0, KEY_READ | KEY_WRITE, NULL, &key, NULL );
+ else
+ res = RegOpenKeyExW( HKEY_LOCAL_MACHINE, combined_path, 0, KEY_READ, &key );
+ HeapFree( GetProcessHeap(), 0, combined_path );
+ return res ? NULL : key;
+ }
+
+ FIXME("unhandled path syntax %s\n", debugstr_w( path ));
+ return NULL;
+}
+
+/* returns TRUE if the given section + name is mapped */
+static BOOL get_mapped_section_key( const WCHAR *filename, const WCHAR *section,
+ const WCHAR *name, BOOL write, HKEY *ret_key )
+{
+ static const WCHAR backslashW[] = {'\\',0};
+ WCHAR *path = NULL, *combined_path;
+ HKEY key, subkey = NULL;
+
+ if (!(key = open_file_mapping_key( filename )))
+ return FALSE;
+
+ if (!RegOpenKeyExW( key, section, 0, KEY_READ, &subkey ))
+ {
+ if (!(path = get_key_value( subkey, name )))
+ path = get_key_value( subkey, NULL );
+ RegCloseKey( subkey );
+ RegCloseKey( key );
+ if (!path) return FALSE;
+ }
+ else
+ {
+ if (!(path = get_key_value( key, section )))
+ {
+ if ((path = get_key_value( key, NULL )))
+ {
+ if ((combined_path = HeapAlloc( GetProcessHeap(), 0,
+ (strlenW( path ) + strlenW( section ) + 2) * sizeof(WCHAR) )))
+ {
+ strcpyW( combined_path, path );
+ strcatW( combined_path, backslashW );
+ strcatW( combined_path, section );
+ }
+ HeapFree( GetProcessHeap(), 0, path );
+ path = combined_path;
+ }
+ }
+ RegCloseKey( key );
+ if (!path) return FALSE;
+ }
+
+ *ret_key = open_mapped_key( path, write );
+ HeapFree( GetProcessHeap(), 0, path );
+ return TRUE;
+}
/********************* API functions **********************************/
@@ -1047,6 +1172,7 @@ INT WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
int ret;
LPWSTR defval_tmp = NULL;
const WCHAR *p;
+ HKEY key;
TRACE("%s,%s,%s,%p,%u,%s\n", debugstr_w(section), debugstr_w(entry),
debugstr_w(def_val), buffer, len, debugstr_w(filename));
@@ -1080,22 +1206,46 @@ INT WINAPI GetPrivateProfileStringW( LPCWSTR section, LPCWSTR entry,
def_val = defval_tmp;
}
- RtlEnterCriticalSection( &PROFILE_CritSect );
-
- if (PROFILE_Open( filename, FALSE ))
+ if (get_mapped_section_key( filename, section, entry, FALSE, &key ))
{
- PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section, entry, FALSE, FALSE );
- PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val, len );
- TRACE("-> %s\n", debugstr_w( buffer ));
+ if (key)
+ {
+ WCHAR *value;
+
+ if ((value = get_key_value( key, entry )))
+ {
+ lstrcpynW( buffer, value, len );
+ HeapFree( GetProcessHeap(), 0, value );
+ }
+ else
+ lstrcpynW( buffer, def_val, len );
+
+ RegCloseKey( key );
+ }
+ else
+ lstrcpynW( buffer, def_val, len );
+
ret = strlenW( buffer );
}
else
{
- lstrcpynW( buffer, def_val, len );
- ret = strlenW( buffer );
- }
+ EnterCriticalSection( &PROFILE_CritSect );
- RtlLeaveCriticalSection( &PROFILE_CritSect );
+ if (PROFILE_Open( filename, FALSE ))
+ {
+ PROFILEKEY *key = PROFILE_Find( &CurProfile->section, section, entry, FALSE, FALSE );
+ PROFILE_CopyEntry( buffer, (key && key->value) ? key->value : def_val, len );
+ TRACE("-> %s\n", debugstr_w( buffer ));
+ ret = strlenW( buffer );
+ }
+ else
+ {
+ lstrcpynW( buffer, def_val, len );
+ ret = strlenW( buffer );
+ }
+
+ LeaveCriticalSection( &PROFILE_CritSect );
+ }
HeapFree(GetProcessHeap(), 0, defval_tmp);
--
2.27.0
More information about the wine-devel
mailing list