Imported Upstream version 9.20
[platform/upstream/7zip.git] / CPP / 7zip / UI / FileManager / RegistryAssociations.cpp
1 // RegistryAssociations.cpp\r
2 \r
3 #include "StdAfx.h"\r
4 \r
5 #include "RegistryAssociations.h"\r
6 \r
7 #include "Common/IntToString.h"\r
8 #include "Common/StringConvert.h"\r
9 #include "Common/StringToInt.h"\r
10 \r
11 #include "Windows/Registry.h"\r
12 #include "Windows/Synchronization.h"\r
13 \r
14 #include "StringUtils.h"\r
15 \r
16 using namespace NWindows;\r
17 using namespace NRegistry;\r
18 \r
19 namespace NRegistryAssociations {\r
20   \r
21 static NSynchronization::CCriticalSection g_CriticalSection;\r
22 \r
23 #define REG_PATH_FM TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR) TEXT("FM")\r
24 \r
25 /*\r
26 \r
27 static const TCHAR *kCUKeyPath = REG_PATH_FM;\r
28 static const WCHAR *kExtPlugins = L"Plugins";\r
29 static const TCHAR *kExtEnabled = TEXT("Enabled");\r
30 \r
31 #define kAssociations TEXT("Associations")\r
32 #define kAssociationsPath REG_PATH_FM TEXT(STRING_PATH_SEPARATOR) kAssociations\r
33 \r
34 bool ReadInternalAssociation(const wchar_t *ext, CExtInfo &extInfo)\r
35 {\r
36   NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
37   CKey key;\r
38   if (key.Open(HKEY_CURRENT_USER,\r
39       CSysString(kAssociationsPath TEXT(STRING_PATH_SEPARATOR)) +\r
40       GetSystemString(ext), KEY_READ) != ERROR_SUCCESS)\r
41     return false;\r
42   UString pluginsString;\r
43   key.QueryValue(kExtPlugins, pluginsString);\r
44   SplitString(pluginsString, extInfo.Plugins);\r
45   return true;\r
46 }\r
47 \r
48 void ReadInternalAssociations(CObjectVector<CExtInfo> &items)\r
49 {\r
50   items.Clear();\r
51   NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
52   CKey associationsKey;\r
53   if (associationsKey.Open(HKEY_CURRENT_USER, kAssociationsPath, KEY_READ) != ERROR_SUCCESS)\r
54     return;\r
55   CSysStringVector extNames;\r
56   associationsKey.EnumKeys(extNames);\r
57   for(int i = 0; i < extNames.Size(); i++)\r
58   {\r
59     const CSysString extName = extNames[i];\r
60     CExtInfo extInfo;\r
61     // extInfo.Enabled = false;\r
62     extInfo.Ext = GetUnicodeString(extName);\r
63     CKey key;\r
64     if (key.Open(associationsKey, extName, KEY_READ) != ERROR_SUCCESS)\r
65       return;\r
66     UString pluginsString;\r
67     key.QueryValue(kExtPlugins, pluginsString);\r
68     SplitString(pluginsString, extInfo.Plugins);\r
69     // if (key.QueryValue(kExtEnabled, extInfo.Enabled) != ERROR_SUCCESS)\r
70     //   extInfo.Enabled = false;\r
71     items.Add(extInfo);\r
72   }\r
73 }\r
74 \r
75 void WriteInternalAssociations(const CObjectVector<CExtInfo> &items)\r
76 {\r
77   NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
78   CKey mainKey;\r
79   mainKey.Create(HKEY_CURRENT_USER, kCUKeyPath);\r
80   mainKey.RecurseDeleteKey(kAssociations);\r
81   CKey associationsKey;\r
82   associationsKey.Create(mainKey, kAssociations);\r
83   for(int i = 0; i < items.Size(); i++)\r
84   {\r
85     const CExtInfo &extInfo = items[i];\r
86     CKey key;\r
87     key.Create(associationsKey, GetSystemString(extInfo.Ext));\r
88     key.SetValue(kExtPlugins, JoinStrings(extInfo.Plugins));\r
89     // key.SetValue(kExtEnabled, extInfo.Enabled);\r
90   }\r
91 }\r
92 */\r
93 \r
94 ///////////////////////////////////\r
95 // External\r
96 \r
97 static const TCHAR *kShellNewKeyName = TEXT("ShellNew");\r
98 static const TCHAR *kShellNewDataValueName = TEXT("Data");\r
99   \r
100 static const TCHAR *kDefaultIconKeyName = TEXT("DefaultIcon");\r
101 static const TCHAR *kShellKeyName = TEXT("shell");\r
102 static const TCHAR *kOpenKeyName = TEXT("open");\r
103 static const TCHAR *kCommandKeyName = TEXT("command");\r
104 static const TCHAR *k7zipPrefix = TEXT("7-Zip.");\r
105 \r
106 static CSysString GetExtensionKeyName(const CSysString &extension)\r
107 {\r
108   return CSysString(TEXT(".")) + extension;\r
109 }\r
110 \r
111 static CSysString GetExtProgramKeyName(const CSysString &extension)\r
112 {\r
113   return CSysString(k7zipPrefix) + extension;\r
114 }\r
115 \r
116 static bool CheckShellExtensionInfo2(const CSysString &extension,\r
117     CSysString programKeyName, UString &iconPath, int &iconIndex)\r
118 {\r
119   iconIndex = -1;\r
120   iconPath.Empty();\r
121   NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
122   CKey extKey;\r
123   if (extKey.Open(HKEY_CLASSES_ROOT, GetExtensionKeyName(extension), KEY_READ) != ERROR_SUCCESS)\r
124     return false;\r
125   if (extKey.QueryValue(NULL, programKeyName) != ERROR_SUCCESS)\r
126     return false;\r
127   UString s = GetUnicodeString(k7zipPrefix);\r
128   if (s.CompareNoCase(GetUnicodeString(programKeyName.Left(s.Length()))) != 0)\r
129     return false;\r
130   CKey iconKey;\r
131   if (extKey.Open(HKEY_CLASSES_ROOT, programKeyName + CSysString(TEXT(CHAR_PATH_SEPARATOR)) + kDefaultIconKeyName, KEY_READ) != ERROR_SUCCESS)\r
132     return false;\r
133   UString value;\r
134   if (extKey.QueryValue(NULL, value) == ERROR_SUCCESS)\r
135   {\r
136     int pos = value.ReverseFind(L',');\r
137     iconPath = value;\r
138     if (pos >= 0)\r
139     {\r
140       const wchar_t *end;\r
141       UInt64 index = ConvertStringToUInt64((const wchar_t *)value + pos + 1, &end);\r
142       if (*end == 0)\r
143       {\r
144         iconIndex = (int)index;\r
145         iconPath = value.Left(pos);\r
146       }\r
147     }\r
148   }\r
149   return true;\r
150 }\r
151 \r
152 bool CheckShellExtensionInfo(const CSysString &extension, UString &iconPath, int &iconIndex)\r
153 {\r
154   NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
155   CSysString programKeyName;\r
156   if (!CheckShellExtensionInfo2(extension, programKeyName, iconPath, iconIndex))\r
157     return false;\r
158   CKey extProgKey;\r
159   return (extProgKey.Open(HKEY_CLASSES_ROOT, programKeyName, KEY_READ) == ERROR_SUCCESS);\r
160 }\r
161 \r
162 static void DeleteShellExtensionKey(const CSysString &extension)\r
163 {\r
164   NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
165   CKey rootKey;\r
166   rootKey.Attach(HKEY_CLASSES_ROOT);\r
167   rootKey.RecurseDeleteKey(GetExtensionKeyName(extension));\r
168   rootKey.Detach();\r
169 }\r
170 \r
171 static void DeleteShellExtensionProgramKey(const CSysString &extension)\r
172 {\r
173   NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
174   CKey rootKey;\r
175   rootKey.Attach(HKEY_CLASSES_ROOT);\r
176   rootKey.RecurseDeleteKey(GetExtProgramKeyName(extension));\r
177   rootKey.Detach();\r
178 }\r
179 \r
180 void DeleteShellExtensionInfo(const CSysString &extension)\r
181 {\r
182   CSysString programKeyName;\r
183   UString iconPath;\r
184   int iconIndex;\r
185   if (CheckShellExtensionInfo2(extension, programKeyName, iconPath, iconIndex))\r
186     DeleteShellExtensionKey(extension);\r
187   DeleteShellExtensionProgramKey(extension);\r
188 }\r
189 \r
190 void AddShellExtensionInfo(const CSysString &extension,\r
191     const UString &programTitle,\r
192     const UString &programOpenCommand,\r
193     const UString &iconPath, int iconIndex,\r
194     const void *shellNewData, int shellNewDataSize)\r
195 {\r
196   DeleteShellExtensionKey(extension);\r
197   DeleteShellExtensionProgramKey(extension);\r
198   NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\r
199   CSysString programKeyName;\r
200   {\r
201     CSysString ext = extension;\r
202     if (iconIndex < 0)\r
203       ext = TEXT("*");\r
204     programKeyName = GetExtProgramKeyName(ext);\r
205   }\r
206   {\r
207     CKey extKey;\r
208     extKey.Create(HKEY_CLASSES_ROOT, GetExtensionKeyName(extension));\r
209     extKey.SetValue(NULL, programKeyName);\r
210     if (shellNewData != NULL)\r
211     {\r
212       CKey shellNewKey;\r
213       shellNewKey.Create(extKey, kShellNewKeyName);\r
214       shellNewKey.SetValue(kShellNewDataValueName, shellNewData, shellNewDataSize);\r
215     }\r
216   }\r
217   CKey programKey;\r
218   programKey.Create(HKEY_CLASSES_ROOT, programKeyName);\r
219   programKey.SetValue(NULL, programTitle);\r
220   {\r
221     CKey iconKey;\r
222     iconKey.Create(programKey, kDefaultIconKeyName);\r
223     UString iconPathFull = iconPath;\r
224     if (iconIndex < 0)\r
225       iconIndex = 0;\r
226     // if (iconIndex >= 0)\r
227     {\r
228       iconPathFull += L",";\r
229       wchar_t s[16];\r
230       ConvertUInt32ToString(iconIndex, s);\r
231       iconPathFull += s;\r
232     }\r
233     iconKey.SetValue(NULL, iconPathFull);\r
234   }\r
235 \r
236   CKey shellKey;\r
237   shellKey.Create(programKey, kShellKeyName);\r
238   shellKey.SetValue(NULL, TEXT(""));\r
239 \r
240   CKey openKey;\r
241   openKey.Create(shellKey, kOpenKeyName);\r
242   openKey.SetValue(NULL, TEXT(""));\r
243   \r
244   CKey commandKey;\r
245   commandKey.Create(openKey, kCommandKeyName);\r
246 \r
247   commandKey.SetValue(NULL, programOpenCommand);\r
248 }\r
249 \r
250 ///////////////////////////\r
251 // ContextMenu\r
252 /*\r
253 \r
254 static const TCHAR *kContextMenuKeyName = TEXT("\\shellex\\ContextMenuHandlers\\7-Zip");\r
255 static const TCHAR *kContextMenuHandlerCLASSIDValue =\r
256     TEXT("{23170F69-40C1-278A-1000-000100020000}");\r
257 static const TCHAR *kRootKeyNameForFile = TEXT("*");\r
258 static const TCHAR *kRootKeyNameForFolder = TEXT("Folder");\r
259 \r
260 static CSysString GetFullContextMenuKeyName(const CSysString &aKeyName)\r
261   { return (aKeyName + kContextMenuKeyName); }\r
262 \r
263 static bool CheckContextMenuHandlerCommon(const CSysString &aKeyName)\r
264 {\r
265   NSynchronization::CCriticalSectionLock lock(&g_CriticalSection, true);\r
266   CKey aKey;\r
267   if (aKey.Open(HKEY_CLASSES_ROOT, GetFullContextMenuKeyName(aKeyName), KEY_READ)\r
268       != ERROR_SUCCESS)\r
269     return false;\r
270   CSysString aValue;\r
271   if (aKey.QueryValue(NULL, aValue) != ERROR_SUCCESS)\r
272     return false;\r
273   return (aValue.CompareNoCase(kContextMenuHandlerCLASSIDValue) == 0);\r
274 }\r
275 \r
276 bool CheckContextMenuHandler()\r
277 {\r
278   return CheckContextMenuHandlerCommon(kRootKeyNameForFile) &&\r
279     CheckContextMenuHandlerCommon(kRootKeyNameForFolder);\r
280 }\r
281 \r
282 static void DeleteContextMenuHandlerCommon(const CSysString &aKeyName)\r
283 {\r
284   CKey rootKey;\r
285   rootKey.Attach(HKEY_CLASSES_ROOT);\r
286   rootKey.RecurseDeleteKey(GetFullContextMenuKeyName(aKeyName));\r
287   rootKey.Detach();\r
288 }\r
289 \r
290 void DeleteContextMenuHandler()\r
291 {\r
292   DeleteContextMenuHandlerCommon(kRootKeyNameForFile);\r
293   DeleteContextMenuHandlerCommon(kRootKeyNameForFolder);\r
294 }\r
295 \r
296 static void AddContextMenuHandlerCommon(const CSysString &aKeyName)\r
297 {\r
298   DeleteContextMenuHandlerCommon(aKeyName);\r
299   NSynchronization::CCriticalSectionLock lock(&g_CriticalSection, true);\r
300   CKey aKey;\r
301   aKey.Create(HKEY_CLASSES_ROOT, GetFullContextMenuKeyName(aKeyName));\r
302   aKey.SetValue(NULL, kContextMenuHandlerCLASSIDValue);\r
303 }\r
304 \r
305 void AddContextMenuHandler()\r
306 {\r
307   AddContextMenuHandlerCommon(kRootKeyNameForFile);\r
308   AddContextMenuHandlerCommon(kRootKeyNameForFolder);\r
309 }\r
310 */\r
311 \r
312 }\r