| ... | @@ -2088,6 +2088,7 @@ pub const LPWSTR = [*:0]WCHAR; | ... | @@ -2088,6 +2088,7 @@ pub const LPWSTR = [*:0]WCHAR; |
| 2088 | pub const LPCWSTR = [*:0]const WCHAR; | 2088 | pub const LPCWSTR = [*:0]const WCHAR; |
| 2089 | pub const PVOID = *anyopaque; | 2089 | pub const PVOID = *anyopaque; |
| 2090 | pub const PWSTR = [*:0]WCHAR; | 2090 | pub const PWSTR = [*:0]WCHAR; |
| | 2091 | pub const PCWSTR = [*:0]const WCHAR; |
| 2091 | pub const SIZE_T = usize; | 2092 | pub const SIZE_T = usize; |
| 2092 | pub const UINT = c_uint; | 2093 | pub const UINT = c_uint; |
| 2093 | pub const ULONG_PTR = usize; | 2094 | pub const ULONG_PTR = usize; |
| ... | @@ -2876,8 +2877,134 @@ pub const ACCESS_MASK = DWORD; | ... | @@ -2876,8 +2877,134 @@ pub const ACCESS_MASK = DWORD; |
| 2876 | pub const LSTATUS = LONG; | 2877 | pub const LSTATUS = LONG; |
| 2877 | | 2878 | |
| 2878 | pub const HKEY = HANDLE; | 2879 | pub const HKEY = HANDLE; |
| | 2880 | |
| 2879 | pub const HKEY_LOCAL_MACHINE: HKEY = @intToPtr(HKEY, 0x80000002); | 2881 | pub const HKEY_LOCAL_MACHINE: HKEY = @intToPtr(HKEY, 0x80000002); |
| 2880 | | 2882 | |
| | 2883 | /// Combines the STANDARD_RIGHTS_REQUIRED, KEY_QUERY_VALUE, KEY_SET_VALUE, KEY_CREATE_SUB_KEY, |
| | 2884 | /// KEY_ENUMERATE_SUB_KEYS, KEY_NOTIFY, and KEY_CREATE_LINK access rights. |
| | 2885 | pub const KEY_ALL_ACCESS = 0xF003F; |
| | 2886 | /// Reserved for system use. |
| | 2887 | pub const KEY_CREATE_LINK = 0x0020; |
| | 2888 | /// Required to create a subkey of a registry key. |
| | 2889 | pub const KEY_CREATE_SUB_KEY = 0x0004; |
| | 2890 | /// Required to enumerate the subkeys of a registry key. |
| | 2891 | pub const KEY_ENUMERATE_SUB_KEYS = 0x0008; |
| | 2892 | /// Equivalent to KEY_READ. |
| | 2893 | pub const KEY_EXECUTE = 0x20019; |
| | 2894 | /// Required to request change notifications for a registry key or for subkeys of a registry key. |
| | 2895 | pub const KEY_NOTIFY = 0x0010; |
| | 2896 | /// Required to query the values of a registry key. |
| | 2897 | pub const KEY_QUERY_VALUE = 0x0001; |
| | 2898 | /// Combines the STANDARD_RIGHTS_READ, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, and KEY_NOTIFY values. |
| | 2899 | pub const KEY_READ = 0x20019; |
| | 2900 | /// Required to create, delete, or set a registry value. |
| | 2901 | pub const KEY_SET_VALUE = 0x0002; |
| | 2902 | /// Indicates that an application on 64-bit Windows should operate on the 32-bit registry view. |
| | 2903 | /// This flag is ignored by 32-bit Windows. |
| | 2904 | pub const KEY_WOW64_32KEY = 0x0200; |
| | 2905 | /// Indicates that an application on 64-bit Windows should operate on the 64-bit registry view. |
| | 2906 | /// This flag is ignored by 32-bit Windows. |
| | 2907 | pub const KEY_WOW64_64KEY = 0x0100; |
| | 2908 | /// Combines the STANDARD_RIGHTS_WRITE, KEY_SET_VALUE, and KEY_CREATE_SUB_KEY access rights. |
| | 2909 | pub const KEY_WRITE = 0x20006; |
| | 2910 | |
| | 2911 | /// Open symbolic link. |
| | 2912 | pub const REG_OPTION_OPEN_LINK: DWORD = 0x8; |
| | 2913 | |
| | 2914 | pub const RTL_QUERY_REGISTRY_TABLE = extern struct { |
| | 2915 | QueryRoutine: RTL_QUERY_REGISTRY_ROUTINE, |
| | 2916 | Flags: ULONG, |
| | 2917 | Name: ?PWSTR, |
| | 2918 | EntryContext: ?*anyopaque, |
| | 2919 | DefaultType: ULONG, |
| | 2920 | DefaultData: ?*anyopaque, |
| | 2921 | DefaultLength: ULONG, |
| | 2922 | }; |
| | 2923 | |
| | 2924 | pub const RTL_QUERY_REGISTRY_ROUTINE = ?std.meta.FnPtr(fn ( |
| | 2925 | PWSTR, |
| | 2926 | ULONG, |
| | 2927 | ?*anyopaque, |
| | 2928 | ULONG, |
| | 2929 | ?*anyopaque, |
| | 2930 | ?*anyopaque, |
| | 2931 | ) callconv(WINAPI) NTSTATUS); |
| | 2932 | |
| | 2933 | /// Path is a full path |
| | 2934 | pub const RTL_REGISTRY_ABSOLUTE = 0; |
| | 2935 | /// \Registry\Machine\System\CurrentControlSet\Services |
| | 2936 | pub const RTL_REGISTRY_SERVICES = 1; |
| | 2937 | /// \Registry\Machine\System\CurrentControlSet\Control |
| | 2938 | pub const RTL_REGISTRY_CONTROL = 2; |
| | 2939 | /// \Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion |
| | 2940 | pub const RTL_REGISTRY_WINDOWS_NT = 3; |
| | 2941 | /// \Registry\Machine\Hardware\DeviceMap |
| | 2942 | pub const RTL_REGISTRY_DEVICEMAP = 4; |
| | 2943 | /// \Registry\User\CurrentUser |
| | 2944 | pub const RTL_REGISTRY_USER = 5; |
| | 2945 | pub const RTL_REGISTRY_MAXIMUM = 6; |
| | 2946 | |
| | 2947 | /// Low order bits are registry handle |
| | 2948 | pub const RTL_REGISTRY_HANDLE = 0x40000000; |
| | 2949 | /// Indicates the key node is optional |
| | 2950 | pub const RTL_REGISTRY_OPTIONAL = 0x80000000; |
| | 2951 | |
| | 2952 | /// Name is a subkey and remainder of table or until next subkey are value |
| | 2953 | /// names for that subkey to look at. |
| | 2954 | pub const RTL_QUERY_REGISTRY_SUBKEY = 0x00000001; |
| | 2955 | |
| | 2956 | /// Reset current key to original key for this and all following table entries. |
| | 2957 | pub const RTL_QUERY_REGISTRY_TOPKEY = 0x00000002; |
| | 2958 | |
| | 2959 | /// Fail if no match found for this table entry. |
| | 2960 | pub const RTL_QUERY_REGISTRY_REQUIRED = 0x00000004; |
| | 2961 | |
| | 2962 | /// Used to mark a table entry that has no value name, just wants a call out, not |
| | 2963 | /// an enumeration of all values. |
| | 2964 | pub const RTL_QUERY_REGISTRY_NOVALUE = 0x00000008; |
| | 2965 | |
| | 2966 | /// Used to suppress the expansion of REG_MULTI_SZ into multiple callouts or |
| | 2967 | /// to prevent the expansion of environment variable values in REG_EXPAND_SZ. |
| | 2968 | pub const RTL_QUERY_REGISTRY_NOEXPAND = 0x00000010; |
| | 2969 | |
| | 2970 | /// QueryRoutine field ignored. EntryContext field points to location to store value. |
| | 2971 | /// For null terminated strings, EntryContext points to UNICODE_STRING structure that |
| | 2972 | /// that describes maximum size of buffer. If .Buffer field is NULL then a buffer is |
| | 2973 | /// allocated. |
| | 2974 | pub const RTL_QUERY_REGISTRY_DIRECT = 0x00000020; |
| | 2975 | |
| | 2976 | /// Used to delete value keys after they are queried. |
| | 2977 | pub const RTL_QUERY_REGISTRY_DELETE = 0x00000040; |
| | 2978 | |
| | 2979 | /// Use this flag with the RTL_QUERY_REGISTRY_DIRECT flag to verify that the REG_XXX type |
| | 2980 | /// of the stored registry value matches the type expected by the caller. |
| | 2981 | /// If the types do not match, the call fails. |
| | 2982 | pub const RTL_QUERY_REGISTRY_TYPECHECK = 0x00000100; |
| | 2983 | |
| | 2984 | /// No value type |
| | 2985 | pub const REG_NONE = 0; |
| | 2986 | /// Unicode nul terminated string |
| | 2987 | pub const REG_SZ = 1; |
| | 2988 | /// Unicode nul terminated string (with environment variable references) |
| | 2989 | pub const REG_EXPAND_SZ = 2; |
| | 2990 | /// Free form binary |
| | 2991 | pub const REG_BINARY = 3; |
| | 2992 | /// 32-bit number |
| | 2993 | pub const REG_DWORD = 4; |
| | 2994 | /// 32-bit number (same as REG_DWORD) |
| | 2995 | pub const REG_DWORD_LITTLE_ENDIAN = 4; |
| | 2996 | /// 32-bit number |
| | 2997 | pub const REG_DWORD_BIG_ENDIAN = 5; |
| | 2998 | /// Symbolic Link (unicode) |
| | 2999 | pub const REG_LINK = 6; |
| | 3000 | /// Multiple Unicode strings |
| | 3001 | pub const REG_MULTI_SZ = 7; |
| | 3002 | /// Resource list in the resource map |
| | 3003 | pub const REG_RESOURCE_LIST = 8; |
| | 3004 | /// Resource list in the hardware description |
| | 3005 | pub const REG_FULL_RESOURCE_DESCRIPTOR = 9; |
| | 3006 | pub const REG_RESOURCE_REQUIREMENTS_LIST = 10; |
| | 3007 | |
| 2881 | pub const FILE_NOTIFY_INFORMATION = extern struct { | 3008 | pub const FILE_NOTIFY_INFORMATION = extern struct { |
| 2882 | NextEntryOffset: DWORD, | 3009 | NextEntryOffset: DWORD, |
| 2883 | Action: DWORD, | 3010 | Action: DWORD, |
| ... | @@ -4020,187 +4147,3 @@ pub fn IsProcessorFeaturePresent(feature: PF) bool { | ... | @@ -4020,187 +4147,3 @@ pub fn IsProcessorFeaturePresent(feature: PF) bool { |
| 4020 | if (@enumToInt(feature) >= PROCESSOR_FEATURE_MAX) return false; | 4147 | if (@enumToInt(feature) >= PROCESSOR_FEATURE_MAX) return false; |
| 4021 | return SharedUserData.ProcessorFeatures[@enumToInt(feature)] == 1; | 4148 | return SharedUserData.ProcessorFeatures[@enumToInt(feature)] == 1; |
| 4022 | } | 4149 | } |
| 4023 | | | |
| 4024 | pub const KEY_QUERY_VALUE = 0x0001; | | |
| 4025 | | | |
| 4026 | /// Open symbolic link. | | |
| 4027 | pub const REG_OPTION_OPEN_LINK: DWORD = 0x8; | | |
| 4028 | | | |
| 4029 | inline fn IsPredefKey(hkey: HKEY) bool { | | |
| 4030 | return @ptrToInt(hkey) & 0xF0000000 == 0x80000000; | | |
| 4031 | } | | |
| 4032 | | | |
| 4033 | inline fn GetPredefKeyIndex(hkey: HKEY) usize { | | |
| 4034 | return @ptrToInt(hkey) & 0x0FFFFFFF; | | |
| 4035 | } | | |
| 4036 | | | |
| 4037 | inline fn ClosePredefKey(hkey: HKEY) void { | | |
| 4038 | if (@ptrToInt(hkey) & 0x1 != 0) { | | |
| 4039 | assert(ntdll.NtClose(hkey) == .SUCCESS); | | |
| 4040 | } | | |
| 4041 | } | | |
| 4042 | | | |
| 4043 | const MAX_DEFAULT_HANDLES = 6; | | |
| 4044 | pub const REG_MAX_NAME_SIZE = 256; | | |
| 4045 | | | |
| 4046 | pub const RegOpenKeyOpts = struct { | | |
| 4047 | ulOptions: DWORD = 0, | | |
| 4048 | samDesired: ACCESS_MASK = KEY_QUERY_VALUE, | | |
| 4049 | }; | | |
| 4050 | | | |
| 4051 | /// Pulls existing key from the registry. | | |
| 4052 | pub fn RegOpenKey(hkey: HKEY, lpSubKey: []const u16, opts: RegOpenKeyOpts) !HKEY { | | |
| 4053 | if (IsPredefKey(hkey) and lpSubKey.len == 0) { | | |
| 4054 | return hkey; | | |
| 4055 | } | | |
| 4056 | | | |
| 4057 | const key_handle = try MapDefaultKey(hkey); | | |
| 4058 | defer ClosePredefKey(key_handle); | | |
| 4059 | | | |
| 4060 | var subkey_string: UNICODE_STRING = undefined; | | |
| 4061 | if (lpSubKey.len == 0 or mem.eql(u16, &[_]u16{'\\'}, lpSubKey)) { | | |
| 4062 | subkey_string = .{ | | |
| 4063 | .Length = 0, | | |
| 4064 | .MaximumLength = 0, | | |
| 4065 | .Buffer = @intToPtr([*]u16, @ptrToInt(&[0]u16{})), | | |
| 4066 | }; | | |
| 4067 | } else { | | |
| 4068 | const len_bytes = math.cast(u16, lpSubKey.len * 2) orelse return error.NameTooLong; | | |
| 4069 | subkey_string = .{ | | |
| 4070 | .Length = len_bytes, | | |
| 4071 | .MaximumLength = len_bytes, | | |
| 4072 | .Buffer = @intToPtr([*]u16, @ptrToInt(lpSubKey.ptr)), | | |
| 4073 | }; | | |
| 4074 | } | | |
| 4075 | | | |
| 4076 | var attributes: ULONG = OBJ_CASE_INSENSITIVE; | | |
| 4077 | if (opts.ulOptions & REG_OPTION_OPEN_LINK != 0) { | | |
| 4078 | attributes |= OBJ_OPENLINK; | | |
| 4079 | } | | |
| 4080 | | | |
| 4081 | var attr = OBJECT_ATTRIBUTES{ | | |
| 4082 | .Length = @sizeOf(OBJECT_ATTRIBUTES), | | |
| 4083 | .RootDirectory = key_handle, | | |
| 4084 | .Attributes = attributes, | | |
| 4085 | .ObjectName = &subkey_string, | | |
| 4086 | .SecurityDescriptor = null, | | |
| 4087 | .SecurityQualityOfService = null, | | |
| 4088 | }; | | |
| 4089 | | | |
| 4090 | var result: HKEY = undefined; | | |
| 4091 | const rc = ntdll.NtOpenKey( | | |
| 4092 | &result, | | |
| 4093 | opts.samDesired, | | |
| 4094 | attr, | | |
| 4095 | ); | | |
| 4096 | switch (rc) { | | |
| 4097 | .SUCCESS => return result, | | |
| 4098 | else => return unexpectedStatus(rc), | | |
| 4099 | } | | |
| 4100 | } | | |
| 4101 | | | |
| 4102 | pub fn RegCloseKey(hkey: HKEY) void { | | |
| 4103 | if (IsPredefKey(hkey)) return; | | |
| 4104 | assert(ntdll.NtClose(hkey) == .SUCCESS); | | |
| 4105 | } | | |
| 4106 | | | |
| 4107 | extern var DefaultHandleHKUDisabled: BOOLEAN; | | |
| 4108 | extern var DefaultHandlesDisabled: BOOLEAN; | | |
| 4109 | extern var DefaultHandleTable: [MAX_DEFAULT_HANDLES]?HANDLE; | | |
| 4110 | | | |
| 4111 | fn MapDefaultKey(key: HKEY) !HANDLE { | | |
| 4112 | if (!IsPredefKey(key)) return @intToPtr(HANDLE, @ptrToInt(key) & ~@as(usize, 0x1)); | | |
| 4113 | | | |
| 4114 | const index = GetPredefKeyIndex(key); | | |
| 4115 | if (index >= MAX_DEFAULT_HANDLES) { | | |
| 4116 | return error.InvalidParameter; | | |
| 4117 | } | | |
| 4118 | | | |
| 4119 | const def_disabled = if (key == HKEY_LOCAL_MACHINE) DefaultHandleHKUDisabled else DefaultHandlesDisabled; | | |
| 4120 | | | |
| 4121 | var handle: HANDLE = undefined; | | |
| 4122 | var do_open: bool = true; | | |
| 4123 | | | |
| 4124 | if (def_disabled != 0) { | | |
| 4125 | const tmp = DefaultHandleTable[index]; | | |
| 4126 | if (tmp) |h| { | | |
| 4127 | do_open = false; | | |
| 4128 | handle = h; | | |
| 4129 | } | | |
| 4130 | } | | |
| 4131 | | | |
| 4132 | if (do_open) { | | |
| 4133 | handle = try OpenPredefinedKey(index); | | |
| 4134 | } | | |
| 4135 | | | |
| 4136 | if (def_disabled == 0) { | | |
| 4137 | handle = @intToPtr(HANDLE, @ptrToInt(handle) | 0x1); | | |
| 4138 | } | | |
| 4139 | | | |
| 4140 | return handle; | | |
| 4141 | } | | |
| 4142 | | | |
| 4143 | fn OpenPredefinedKey(index: usize) !HANDLE { | | |
| 4144 | switch (index) { | | |
| 4145 | 0 => { | | |
| 4146 | // HKEY_CLASSES_ROOT | | |
| 4147 | return error.Unimplemented; | | |
| 4148 | }, | | |
| 4149 | 1 => { | | |
| 4150 | // HKEY_CURRENT_USER | | |
| 4151 | return error.Unimplemented; | | |
| 4152 | }, | | |
| 4153 | 2 => { | | |
| 4154 | // HKEY_LOCAL_MACHINE | | |
| 4155 | return OpenLocalMachineKey(); | | |
| 4156 | }, | | |
| 4157 | 3 => { | | |
| 4158 | // HKEY_USERS | | |
| 4159 | return error.Unimplemented; | | |
| 4160 | }, | | |
| 4161 | 5 => { | | |
| 4162 | // HKEY_CURRENT_CONFIG | | |
| 4163 | return error.Unimplemented; | | |
| 4164 | }, | | |
| 4165 | 6 => { | | |
| 4166 | // HKEY_DYN_DATA | | |
| 4167 | return error.Unimplemented; | | |
| 4168 | }, | | |
| 4169 | else => { | | |
| 4170 | return error.InvalidParameter; | | |
| 4171 | }, | | |
| 4172 | } | | |
| 4173 | } | | |
| 4174 | | | |
| 4175 | fn OpenLocalMachineKey() !HANDLE { | | |
| 4176 | const path = "\\Registry\\Machine"; | | |
| 4177 | var path_u16: [REG_MAX_NAME_SIZE]u16 = undefined; | | |
| 4178 | const path_len_u16 = try std.unicode.utf8ToUtf16Le(&path_u16, path); | | |
| 4179 | const path_len_bytes = @intCast(u16, path_len_u16 * 2); | | |
| 4180 | | | |
| 4181 | var key_name = UNICODE_STRING{ | | |
| 4182 | .Length = path_len_bytes, | | |
| 4183 | .MaximumLength = path_len_bytes, | | |
| 4184 | .Buffer = @intToPtr([*]u16, @ptrToInt(&path_u16)), | | |
| 4185 | }; | | |
| 4186 | | | |
| 4187 | var attr = OBJECT_ATTRIBUTES{ | | |
| 4188 | .Length = @sizeOf(OBJECT_ATTRIBUTES), | | |
| 4189 | .RootDirectory = null, | | |
| 4190 | .Attributes = OBJ_CASE_INSENSITIVE, | | |
| 4191 | .ObjectName = &key_name, | | |
| 4192 | .SecurityDescriptor = null, | | |
| 4193 | .SecurityQualityOfService = null, | | |
| 4194 | }; | | |
| 4195 | | | |
| 4196 | var result: HKEY = undefined; | | |
| 4197 | const rc = ntdll.NtOpenKey( | | |
| 4198 | &result, | | |
| 4199 | MAXIMUM_ALLOWED, | | |
| 4200 | attr, | | |
| 4201 | ); | | |
| 4202 | switch (rc) { | | |
| 4203 | .SUCCESS => return result, | | |
| 4204 | else => return unexpectedStatus(rc), | | |
| 4205 | } | | |
| 4206 | } | | |