diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index 182d5f122a5..7913c5ed7bc 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -46,7 +46,8 @@ struct display_mode_descriptor BOOL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmode, DWORD flags); -static const char initial_mode_key[] = "Initial Display Mode"; +static const WCHAR initial_mode_keyW[] = {'I','n','i','t','i','a','l',' ','D','i','s','p','l','a','y', + ' ','M','o','d','e'}; static const WCHAR pixelencodingW[] = {'P','i','x','e','l','E','n','c','o','d','i','n','g',0}; static CFArrayRef modes; @@ -301,13 +302,14 @@ static void init_original_display_mode(void) return; /* @@ Wine registry key: HKLM\Software\Wine\Mac Driver */ - if (RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Mac Driver", 0, NULL, - 0, KEY_ALL_ACCESS, NULL, &mac_driver_hkey, NULL)) + mac_driver_hkey = reg_create_ascii_key(NULL, "\\Registry\\Machine\\Software\\Wine\\Mac Driver", + 0, NULL); + if (!mac_driver_hkey) return; /* @@ Wine registry key: HKLM\Software\Wine\Mac Driver\Initial Display Mode */ - if (RegCreateKeyExA(mac_driver_hkey, initial_mode_key, 0, NULL, - REG_OPTION_VOLATILE, KEY_WRITE, NULL, &parent_hkey, &disposition)) + if (!(parent_hkey = reg_create_key(mac_driver_hkey, initial_mode_keyW, sizeof(initial_mode_keyW), + REG_OPTION_VOLATILE, &disposition))) { parent_hkey = NULL; goto fail; @@ -332,10 +334,10 @@ done: fail: macdrv_free_displays(displays); - RegCloseKey(parent_hkey); + NtClose(parent_hkey); if (!success && parent_hkey) - RegDeleteTreeA(mac_driver_hkey, initial_mode_key); - RegCloseKey(mac_driver_hkey); + reg_delete_tree(mac_driver_hkey, initial_mode_keyW, sizeof(initial_mode_keyW)); + NtClose(mac_driver_hkey); if (success) inited_original_display_mode = TRUE; } diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index c216cfb994f..922a2df75cb 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -297,6 +297,11 @@ extern void macdrv_process_text_input(UINT vkey, UINT scan, UINT repeat, const B extern ULONG query_reg_value(HKEY hkey, const WCHAR *name, KEY_VALUE_PARTIAL_INFORMATION *info, ULONG size) DECLSPEC_HIDDEN; +extern HKEY reg_create_ascii_key(HKEY root, const char *name, DWORD options, + DWORD *disposition) DECLSPEC_HIDDEN; +extern HKEY reg_create_key(HKEY root, const WCHAR *name, ULONG name_len, + DWORD options, DWORD *disposition) DECLSPEC_HIDDEN; +extern BOOL reg_delete_tree(HKEY parent, const WCHAR *name, ULONG name_len) DECLSPEC_HIDDEN; extern HKEY reg_open_key(HKEY root, const WCHAR *name, ULONG name_len) DECLSPEC_HIDDEN; /* string helpers */ diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c index 134842bbbfb..b168e12439c 100644 --- a/dlls/winemac.drv/macdrv_main.c +++ b/dlls/winemac.drv/macdrv_main.c @@ -24,6 +24,8 @@ #include #include +#include "ntstatus.h" +#define WIN32_NO_STATUS #include "macdrv.h" #include "winuser.h" #include "winreg.h" @@ -152,6 +154,83 @@ static HKEY open_hkcu_key(const char *name) } +/* wrapper for NtCreateKey that creates the key recursively if necessary */ +HKEY reg_create_key(HKEY root, const WCHAR *name, ULONG name_len, + DWORD options, DWORD *disposition) +{ + UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name }; + OBJECT_ATTRIBUTES attr; + NTSTATUS status; + HANDLE ret; + + attr.Length = sizeof(attr); + attr.RootDirectory = root; + attr.ObjectName = &nameW; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + + status = NtCreateKey(&ret, MAXIMUM_ALLOWED, &attr, 0, NULL, options, disposition); + if (status == STATUS_OBJECT_NAME_NOT_FOUND) + { + static const WCHAR registry_rootW[] = { '\\','R','e','g','i','s','t','r','y','\\' }; + DWORD pos = 0, i = 0, len = name_len / sizeof(WCHAR); + + /* don't try to create registry root */ + if (!root && len > ARRAY_SIZE(registry_rootW) && + !memcmp(name, registry_rootW, sizeof(registry_rootW))) + i += ARRAY_SIZE(registry_rootW); + + while (i < len && name[i] != '\\') i++; + if (i == len) return 0; + for (;;) + { + unsigned int subkey_options = options; + if (i < len) subkey_options &= ~(REG_OPTION_CREATE_LINK | REG_OPTION_OPEN_LINK); + nameW.Buffer = (WCHAR *)name + pos; + nameW.Length = (i - pos) * sizeof(WCHAR); + status = NtCreateKey(&ret, MAXIMUM_ALLOWED, &attr, 0, NULL, subkey_options, disposition); + + if (attr.RootDirectory != root) NtClose(attr.RootDirectory); + if (!NT_SUCCESS(status)) return 0; + if (i == len) break; + attr.RootDirectory = ret; + while (i < len && name[i] == '\\') i++; + pos = i; + while (i < len && name[i] != '\\') i++; + } + } + return ret; +} + + +HKEY reg_create_ascii_key(HKEY root, const char *name, DWORD options, DWORD *disposition) +{ + WCHAR buf[256]; + return reg_create_key(root, buf, asciiz_to_unicode(buf, name) - sizeof(WCHAR), + options, disposition); +} + + +BOOL reg_delete_tree(HKEY parent, const WCHAR *name, ULONG name_len) +{ + char buffer[4096]; + KEY_NODE_INFORMATION *key_info = (KEY_NODE_INFORMATION *)buffer; + DWORD size; + HKEY key; + BOOL ret = TRUE; + + if (!(key = reg_open_key(parent, name, name_len))) return FALSE; + + while (ret && !NtEnumerateKey(key, 0, KeyNodeInformation, key_info, sizeof(buffer), &size)) + ret = reg_delete_tree(key, key_info->Name, key_info->NameLength); + + if (ret) ret = !NtDeleteKey(key); + NtClose(key); + return ret; +} + + ULONG query_reg_value(HKEY hkey, const WCHAR *name, KEY_VALUE_PARTIAL_INFORMATION *info, ULONG size) { UNICODE_STRING str;