forked from jrsoftware/issrc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFileAssocFunc.pas
188 lines (155 loc) · 7.08 KB
/
FileAssocFunc.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
unit FileAssocFunc;
{
Inno Setup
Copyright (C) 1997-2020 Jordan Russell
Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT.
Compiler IDE's functions for registering/unregistering the .iss file association
}
interface
function RegisterISSFileAssociation(const AllowInteractive: Boolean; var AllUsers: Boolean): Boolean;
procedure UnregisterISSFileAssociation;
implementation
uses
Windows, SysUtils, PathFunc, ShlObj, CmnFunc, CmnFunc2;
function GetRootkey: HKEY;
begin
if IsAdminLoggedOn then
Result := HKEY_LOCAL_MACHINE
else
Result := HKEY_CURRENT_USER;
end;
procedure UnregisterISSFileAssociationDo(const Rootkey: HKEY; const ChangeNotify: Boolean); forward;
function RegisterISSFileAssociation(const AllowInteractive: Boolean; var AllUsers: Boolean): Boolean;
procedure SetKeyValue(const Rootkey: HKEY; const Subkey, ValueName: PChar; const Data: String);
procedure Check(const Res: Longint);
begin
if Res <> ERROR_SUCCESS then
raise Exception.CreateFmt('Error creating file association:'#13#10'%d - %s',
[Res, Win32ErrorString(Res)]);
end;
var
K: HKEY;
Disp: DWORD;
begin
Check(RegCreateKeyExView(rvDefault, Rootkey, Subkey, 0, nil, 0, KEY_SET_VALUE,
nil, K, @Disp));
try
Check(RegSetValueEx(K, ValueName, 0, REG_SZ, PChar(Data), (Length(Data)+1)*SizeOf(Data[1])));
finally
RegCloseKey(K);
end;
end;
var
SelfName: String;
Rootkey: HKEY;
begin
Rootkey := GetRootkey;
AllUsers := Rootkey = HKEY_LOCAL_MACHINE;
Result := AllUsers or not AllowInteractive or
(MsgBox('Unable to associate for all users without administrative privileges. Do you want to associate only for yourself instead?',
'Associate', mbConfirmation, MB_YESNO) = IDYES);
if not Result then
Exit;
SelfName := NewParamStr(0);
SetKeyValue(Rootkey, 'Software\Classes\.iss', nil, 'InnoSetupScriptFile');
SetKeyValue(Rootkey, 'Software\Classes\.iss', 'Content Type', 'text/plain');
SetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile', nil, 'Inno Setup Script');
SetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile\DefaultIcon', nil, SelfName + ',1');
SetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\open\command', nil,
'"' + SelfName + '" "%1"');
SetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\OpenWithInnoSetup', nil,
'Open with &Inno Setup');
SetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\OpenWithInnoSetup\command', nil,
'"' + SelfName + '" "%1"');
SetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\Compile', nil, 'Compi&le');
SetKeyValue(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\Compile\command', nil,
'"' + SelfName + '" /cc "%1"');
SetKeyValue(Rootkey, PChar('Software\Classes\Applications\' + PathExtractName(SelfName) + '\SupportedTypes'), '.iss', '');
{ If we just associated for all users, remove our existing association for the current user if it exists. }
if AllUsers then
UnregisterISSFileAssociationDo(HKEY_CURRENT_USER, False);
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
end;
procedure UnregisterISSFileAssociationDo(const Rootkey: HKEY; const ChangeNotify: Boolean);
function KeyValueEquals(const Rootkey: HKEY; const Subkey: PChar; const Data: String): Boolean;
var
K: HKEY;
S: String;
begin
Result := False;
if RegOpenKeyExView(rvDefault, Rootkey, Subkey, 0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
if RegQueryStringValue(K, nil, S) and (PathCompare(Data, S) = 0) then
Result := True;
RegCloseKey(K);
end;
end;
function KeyExists(const Rootkey: HKEY; const Subkey: PChar): Boolean;
var
K: HKEY;
begin
Result := (RegOpenKeyExView(rvDefault, Rootkey, Subkey, 0, KEY_QUERY_VALUE,
K) = ERROR_SUCCESS);
if Result then
RegCloseKey(K);
end;
function GetKeyNumSubkeysValues(const Rootkey: HKEY; const Subkey: PChar;
var NumSubkeys, NumValues: DWORD): Boolean;
var
K: HKEY;
begin
Result := False;
if RegOpenKeyExView(rvDefault, Rootkey, Subkey, 0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
Result := RegQueryInfoKey(K, nil, nil, nil, @NumSubkeys, nil, nil,
@NumValues, nil, nil, nil, nil) = ERROR_SUCCESS;
RegCloseKey(K);
end;
end;
procedure DeleteValue(const Rootkey: HKEY; const Subkey, ValueName: PChar);
var
K: HKEY;
begin
if RegOpenKeyExView(rvDefault, Rootkey, Subkey, 0, KEY_SET_VALUE, K) = ERROR_SUCCESS then begin
RegDeleteValue(K, ValueName);
RegCloseKey(K);
end;
end;
var
SelfName: String;
NumSubkeys, NumValues: DWORD;
begin
if not KeyExists(Rootkey, 'Software\Classes\InnoSetupScriptFile') and not KeyExists(Rootkey, 'Software\Classes\.iss') then
Exit;
SelfName := NewParamStr(0);
{ NOTE: We can't just blindly delete the entire .iss & InnoSetupScriptFile
keys, otherwise we'd remove the association even if we weren't the one who
registered it in the first place. }
{ Clean up 'InnoSetupScriptFile' }
if KeyValueEquals(Rootkey, 'Software\Classes\InnoSetupScriptFile\DefaultIcon', SelfName + ',1') then
RegDeleteKeyIncludingSubkeys(rvDefault, Rootkey, 'Software\Classes\InnoSetupScriptFile\DefaultIcon');
if KeyValueEquals(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\open\command', '"' + SelfName + '" "%1"') then
RegDeleteKeyIncludingSubkeys(rvDefault, Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\open');
if KeyValueEquals(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\OpenWithInnoSetup\command', '"' + SelfName + '" "%1"') then
RegDeleteKeyIncludingSubkeys(rvDefault, Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\OpenWithInnoSetup');
if KeyValueEquals(Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\Compile\command', '"' + SelfName + '" /cc "%1"') then
RegDeleteKeyIncludingSubkeys(rvDefault, Rootkey, 'Software\Classes\InnoSetupScriptFile\shell\Compile');
RegDeleteKeyIfEmpty(rvDefault, Rootkey, 'Software\Classes\InnoSetupScriptFile\shell');
if KeyValueEquals(Rootkey, 'Software\Classes\InnoSetupScriptFile', 'Inno Setup Script') and
GetKeyNumSubkeysValues(Rootkey, 'Software\Classes\InnoSetupScriptFile', NumSubkeys, NumValues) and
(NumSubkeys = 0) and (NumValues <= 1) then
RegDeleteKey(Rootkey, 'Software\Classes\InnoSetupScriptFile');
{ Clean up '.iss' }
if not KeyExists(Rootkey, 'Software\Classes\InnoSetupScriptFile') and
KeyValueEquals(Rootkey, 'Software\Classes\.iss', 'InnoSetupScriptFile') then begin
DeleteValue(Rootkey, 'Software\Classes\.iss', nil);
DeleteValue(Rootkey, 'Software\Classes\.iss', 'Content Type');
end;
RegDeleteKeyIfEmpty(rvDefault, RootKey, 'Software\Classes\.iss');
if ChangeNotify then
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
end;
procedure UnregisterISSFileAssociation;
begin
UnregisterISSFileAssociationDo(GetRootkey, True);
end;
end.