diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index d13a2277e61..bded3500bee 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -293,4 +293,21 @@ extern void macdrv_process_text_input(UINT vkey, UINT scan, UINT repeat, const B extern void macdrv_sent_text_input(const macdrv_event *event) DECLSPEC_HIDDEN; extern BOOL query_ime_char_rect(macdrv_query* query) DECLSPEC_HIDDEN; +/* string helpers */ + +static inline void ascii_to_unicode(WCHAR *dst, const char *src, size_t len) +{ + while (len--) *dst++ = (unsigned char)*src++; +} + +static inline UINT asciiz_to_unicode(WCHAR *dst, const char *src) +{ + WCHAR *p = dst; + while ((*p++ = *src++)); + return (p - dst) * sizeof(WCHAR); +} + +/* FIXME: remove once we use unixlib */ +#define wcsrchr strrchrW + #endif /* __WINE_MACDRV_H */ diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c index fff72589417..fccd588c271 100644 --- a/dlls/winemac.drv/macdrv_main.c +++ b/dlls/winemac.drv/macdrv_main.c @@ -28,6 +28,7 @@ #include "winuser.h" #include "winreg.h" #include "wine/server.h" +#include "wine/unicode.h" WINE_DEFAULT_DEBUG_CHANNEL(macdrv); @@ -102,16 +103,97 @@ const char* debugstr_cf(CFTypeRef t) } +static HKEY reg_open_key(HKEY root, const WCHAR *name, ULONG name_len) +{ + UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name }; + OBJECT_ATTRIBUTES attr; + HANDLE ret; + + attr.Length = sizeof(attr); + attr.RootDirectory = root; + attr.ObjectName = &nameW; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + + return NtOpenKeyEx(&ret, MAXIMUM_ALLOWED, &attr, 0) ? 0 : ret; +} + + +static HKEY open_hkcu_key(const char *name) +{ + WCHAR bufferW[256]; + static HKEY hkcu; + + if (!hkcu) + { + char buffer[256]; + DWORD_PTR sid_data[(sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE) / sizeof(DWORD_PTR)]; + DWORD i, len = sizeof(sid_data); + SID *sid; + + if (NtQueryInformationToken(GetCurrentThreadEffectiveToken(), TokenUser, sid_data, len, &len)) + return 0; + + sid = ((TOKEN_USER *)sid_data)->User.Sid; + len = sprintf(buffer, "\\Registry\\User\\S-%u-%u", sid->Revision, + MAKELONG(MAKEWORD(sid->IdentifierAuthority.Value[5], + sid->IdentifierAuthority.Value[4]), + MAKEWORD(sid->IdentifierAuthority.Value[3], + sid->IdentifierAuthority.Value[2]))); + for (i = 0; i < sid->SubAuthorityCount; i++) + len += sprintf(buffer + len, "-%u", sid->SubAuthority[i]); + + ascii_to_unicode(bufferW, buffer, len); + hkcu = reg_open_key(NULL, bufferW, len * sizeof(WCHAR)); + } + + return reg_open_key(hkcu, bufferW, asciiz_to_unicode(bufferW, name) - sizeof(WCHAR)); +} + + +static ULONG query_reg_value(HKEY hkey, const WCHAR *name, KEY_VALUE_PARTIAL_INFORMATION *info, ULONG size) +{ + UNICODE_STRING str; + + RtlInitUnicodeString(&str, name); + if (NtQueryValueKey(hkey, &str, KeyValuePartialInformation, info, size, &size)) + return 0; + + return size - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data); +} + + /*********************************************************************** * get_config_key * * Get a config key from either the app-specific or the default config */ static inline DWORD get_config_key(HKEY defkey, HKEY appkey, const char *name, - char *buffer, DWORD size) + WCHAR *buffer, DWORD size) { - if (appkey && !RegQueryValueExA(appkey, name, 0, NULL, (LPBYTE)buffer, &size)) return 0; - if (defkey && !RegQueryValueExA(defkey, name, 0, NULL, (LPBYTE)buffer, &size)) return 0; + WCHAR nameW[128]; + char buf[2048]; + KEY_VALUE_PARTIAL_INFORMATION *info = (void *)buf; + + asciiz_to_unicode(nameW, name); + + if (appkey && query_reg_value(appkey, nameW, info, sizeof(buf))) + { + size = min(info->DataLength, size - sizeof(WCHAR)); + memcpy(buffer, info->Data, size); + buffer[size / sizeof(WCHAR)] = 0; + return 0; + } + + if (defkey && query_reg_value(defkey, nameW, info, sizeof(buf))) + { + size = min(info->DataLength, size - sizeof(WCHAR)); + memcpy(buffer, info->Data, size); + buffer[size / sizeof(WCHAR)] = 0; + return 0; + } + return ERROR_FILE_NOT_FOUND; } @@ -123,36 +205,41 @@ static inline DWORD get_config_key(HKEY defkey, HKEY appkey, const char *name, */ static void setup_options(void) { - char buffer[MAX_PATH + 16]; + static const WCHAR macdriverW[] = {'\\','M','a','c',' ','D','r','i','v','e','r',0}; + WCHAR buffer[MAX_PATH + 16], *p, *appname; HKEY hkey, appkey = 0; DWORD len; /* @@ Wine registry key: HKCU\Software\Wine\Mac Driver */ - if (RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Mac Driver", &hkey)) hkey = 0; + hkey = open_hkcu_key("Software\\Wine\\Mac Driver"); /* open the app-specific key */ - len = GetModuleFileNameA(0, buffer, MAX_PATH); + appname = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer; + if ((p = wcsrchr(appname, '/'))) appname = p + 1; + if ((p = wcsrchr(appname, '\\'))) appname = p + 1; + len = lstrlenW(appname); + if (len && len < MAX_PATH) { HKEY tmpkey; - char *p, *appname = buffer; - if ((p = strrchr(appname, '/'))) appname = p + 1; - if ((p = strrchr(appname, '\\'))) appname = p + 1; - strcat(appname, "\\Mac Driver"); + memcpy(buffer, appname, len * sizeof(WCHAR)); + memcpy(buffer + len, macdriverW, sizeof(macdriverW)); /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\Mac Driver */ - if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey)) + if ((tmpkey = open_hkcu_key("Software\\Wine\\AppDefaults"))) { - if (RegOpenKeyA(tmpkey, appname, &appkey)) appkey = 0; - RegCloseKey(tmpkey); + appkey = reg_open_key(tmpkey, buffer, lstrlenW(buffer) * sizeof(WCHAR)); + NtClose(tmpkey); } } if (!get_config_key(hkey, appkey, "WindowsFloatWhenInactive", buffer, sizeof(buffer))) { - if (!strcmp(buffer, "none")) + static const WCHAR noneW[] = {'n','o','n','e',0}; + static const WCHAR allW[] = {'a','l','l',0}; + if (!lstrcmpW(buffer, noneW)) topmost_float_inactive = TOPMOST_FLOAT_INACTIVE_NONE; - else if (!strcmp(buffer, "all")) + else if (!lstrcmpW(buffer, allW)) topmost_float_inactive = TOPMOST_FLOAT_INACTIVE_ALL; else topmost_float_inactive = TOPMOST_FLOAT_INACTIVE_NONFULLSCREEN; @@ -206,9 +293,11 @@ static void setup_options(void) if (!get_config_key(hkey, appkey, "OpenGLSurfaceMode", buffer, sizeof(buffer))) { - if (!strcmp(buffer, "transparent")) + static const WCHAR transparentW[] = {'t','r','a','n','s','p','a','r','e','n','t',0}; + static const WCHAR behindW[] = {'b','e','h','i','n','d',0}; + if (!lstrcmpW(buffer, transparentW)) gl_surface_mode = GL_SURFACE_IN_FRONT_TRANSPARENT; - else if (!strcmp(buffer, "behind")) + else if (!lstrcmpW(buffer, behindW)) gl_surface_mode = GL_SURFACE_BEHIND; else gl_surface_mode = GL_SURFACE_IN_FRONT_OPAQUE; @@ -222,8 +311,8 @@ static void setup_options(void) if (!get_config_key(hkey, NULL, "RetinaMode", buffer, sizeof(buffer))) retina_enabled = IS_OPTION_TRUE(buffer[0]); - if (appkey) RegCloseKey(appkey); - if (hkey) RegCloseKey(hkey); + if (appkey) NtClose(appkey); + if (hkey) NtClose(hkey); }