1 // RegistryAssociations.cpp
\r
5 #include "RegistryAssociations.h"
\r
7 #include "Common/IntToString.h"
\r
8 #include "Common/StringConvert.h"
\r
9 #include "Common/StringToInt.h"
\r
11 #include "Windows/Registry.h"
\r
12 #include "Windows/Synchronization.h"
\r
14 #include "StringUtils.h"
\r
16 using namespace NWindows;
\r
17 using namespace NRegistry;
\r
19 namespace NRegistryAssociations {
\r
21 static NSynchronization::CCriticalSection g_CriticalSection;
\r
23 #define REG_PATH_FM TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR) TEXT("FM")
\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
31 #define kAssociations TEXT("Associations")
\r
32 #define kAssociationsPath REG_PATH_FM TEXT(STRING_PATH_SEPARATOR) kAssociations
\r
34 bool ReadInternalAssociation(const wchar_t *ext, CExtInfo &extInfo)
\r
36 NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
\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
42 UString pluginsString;
\r
43 key.QueryValue(kExtPlugins, pluginsString);
\r
44 SplitString(pluginsString, extInfo.Plugins);
\r
48 void ReadInternalAssociations(CObjectVector<CExtInfo> &items)
\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
55 CSysStringVector extNames;
\r
56 associationsKey.EnumKeys(extNames);
\r
57 for(int i = 0; i < extNames.Size(); i++)
\r
59 const CSysString extName = extNames[i];
\r
61 // extInfo.Enabled = false;
\r
62 extInfo.Ext = GetUnicodeString(extName);
\r
64 if (key.Open(associationsKey, extName, KEY_READ) != ERROR_SUCCESS)
\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
75 void WriteInternalAssociations(const CObjectVector<CExtInfo> &items)
\r
77 NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
\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
85 const CExtInfo &extInfo = items[i];
\r
87 key.Create(associationsKey, GetSystemString(extInfo.Ext));
\r
88 key.SetValue(kExtPlugins, JoinStrings(extInfo.Plugins));
\r
89 // key.SetValue(kExtEnabled, extInfo.Enabled);
\r
94 ///////////////////////////////////
\r
97 static const TCHAR *kShellNewKeyName = TEXT("ShellNew");
\r
98 static const TCHAR *kShellNewDataValueName = TEXT("Data");
\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
106 static CSysString GetExtensionKeyName(const CSysString &extension)
\r
108 return CSysString(TEXT(".")) + extension;
\r
111 static CSysString GetExtProgramKeyName(const CSysString &extension)
\r
113 return CSysString(k7zipPrefix) + extension;
\r
116 static bool CheckShellExtensionInfo2(const CSysString &extension,
\r
117 CSysString programKeyName, UString &iconPath, int &iconIndex)
\r
121 NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
\r
123 if (extKey.Open(HKEY_CLASSES_ROOT, GetExtensionKeyName(extension), KEY_READ) != ERROR_SUCCESS)
\r
125 if (extKey.QueryValue(NULL, programKeyName) != ERROR_SUCCESS)
\r
127 UString s = GetUnicodeString(k7zipPrefix);
\r
128 if (s.CompareNoCase(GetUnicodeString(programKeyName.Left(s.Length()))) != 0)
\r
131 if (extKey.Open(HKEY_CLASSES_ROOT, programKeyName + CSysString(TEXT(CHAR_PATH_SEPARATOR)) + kDefaultIconKeyName, KEY_READ) != ERROR_SUCCESS)
\r
134 if (extKey.QueryValue(NULL, value) == ERROR_SUCCESS)
\r
136 int pos = value.ReverseFind(L',');
\r
140 const wchar_t *end;
\r
141 UInt64 index = ConvertStringToUInt64((const wchar_t *)value + pos + 1, &end);
\r
144 iconIndex = (int)index;
\r
145 iconPath = value.Left(pos);
\r
152 bool CheckShellExtensionInfo(const CSysString &extension, UString &iconPath, int &iconIndex)
\r
154 NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
\r
155 CSysString programKeyName;
\r
156 if (!CheckShellExtensionInfo2(extension, programKeyName, iconPath, iconIndex))
\r
159 return (extProgKey.Open(HKEY_CLASSES_ROOT, programKeyName, KEY_READ) == ERROR_SUCCESS);
\r
162 static void DeleteShellExtensionKey(const CSysString &extension)
\r
164 NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
\r
166 rootKey.Attach(HKEY_CLASSES_ROOT);
\r
167 rootKey.RecurseDeleteKey(GetExtensionKeyName(extension));
\r
171 static void DeleteShellExtensionProgramKey(const CSysString &extension)
\r
173 NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
\r
175 rootKey.Attach(HKEY_CLASSES_ROOT);
\r
176 rootKey.RecurseDeleteKey(GetExtProgramKeyName(extension));
\r
180 void DeleteShellExtensionInfo(const CSysString &extension)
\r
182 CSysString programKeyName;
\r
185 if (CheckShellExtensionInfo2(extension, programKeyName, iconPath, iconIndex))
\r
186 DeleteShellExtensionKey(extension);
\r
187 DeleteShellExtensionProgramKey(extension);
\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
196 DeleteShellExtensionKey(extension);
\r
197 DeleteShellExtensionProgramKey(extension);
\r
198 NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
\r
199 CSysString programKeyName;
\r
201 CSysString ext = extension;
\r
204 programKeyName = GetExtProgramKeyName(ext);
\r
208 extKey.Create(HKEY_CLASSES_ROOT, GetExtensionKeyName(extension));
\r
209 extKey.SetValue(NULL, programKeyName);
\r
210 if (shellNewData != NULL)
\r
213 shellNewKey.Create(extKey, kShellNewKeyName);
\r
214 shellNewKey.SetValue(kShellNewDataValueName, shellNewData, shellNewDataSize);
\r
218 programKey.Create(HKEY_CLASSES_ROOT, programKeyName);
\r
219 programKey.SetValue(NULL, programTitle);
\r
222 iconKey.Create(programKey, kDefaultIconKeyName);
\r
223 UString iconPathFull = iconPath;
\r
226 // if (iconIndex >= 0)
\r
228 iconPathFull += L",";
\r
230 ConvertUInt32ToString(iconIndex, s);
\r
233 iconKey.SetValue(NULL, iconPathFull);
\r
237 shellKey.Create(programKey, kShellKeyName);
\r
238 shellKey.SetValue(NULL, TEXT(""));
\r
241 openKey.Create(shellKey, kOpenKeyName);
\r
242 openKey.SetValue(NULL, TEXT(""));
\r
245 commandKey.Create(openKey, kCommandKeyName);
\r
247 commandKey.SetValue(NULL, programOpenCommand);
\r
250 ///////////////////////////
\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
260 static CSysString GetFullContextMenuKeyName(const CSysString &aKeyName)
\r
261 { return (aKeyName + kContextMenuKeyName); }
\r
263 static bool CheckContextMenuHandlerCommon(const CSysString &aKeyName)
\r
265 NSynchronization::CCriticalSectionLock lock(&g_CriticalSection, true);
\r
267 if (aKey.Open(HKEY_CLASSES_ROOT, GetFullContextMenuKeyName(aKeyName), KEY_READ)
\r
271 if (aKey.QueryValue(NULL, aValue) != ERROR_SUCCESS)
\r
273 return (aValue.CompareNoCase(kContextMenuHandlerCLASSIDValue) == 0);
\r
276 bool CheckContextMenuHandler()
\r
278 return CheckContextMenuHandlerCommon(kRootKeyNameForFile) &&
\r
279 CheckContextMenuHandlerCommon(kRootKeyNameForFolder);
\r
282 static void DeleteContextMenuHandlerCommon(const CSysString &aKeyName)
\r
285 rootKey.Attach(HKEY_CLASSES_ROOT);
\r
286 rootKey.RecurseDeleteKey(GetFullContextMenuKeyName(aKeyName));
\r
290 void DeleteContextMenuHandler()
\r
292 DeleteContextMenuHandlerCommon(kRootKeyNameForFile);
\r
293 DeleteContextMenuHandlerCommon(kRootKeyNameForFolder);
\r
296 static void AddContextMenuHandlerCommon(const CSysString &aKeyName)
\r
298 DeleteContextMenuHandlerCommon(aKeyName);
\r
299 NSynchronization::CCriticalSectionLock lock(&g_CriticalSection, true);
\r
301 aKey.Create(HKEY_CLASSES_ROOT, GetFullContextMenuKeyName(aKeyName));
\r
302 aKey.SetValue(NULL, kContextMenuHandlerCLASSIDValue);
\r
305 void AddContextMenuHandler()
\r
307 AddContextMenuHandlerCommon(kRootKeyNameForFile);
\r
308 AddContextMenuHandlerCommon(kRootKeyNameForFolder);
\r