[RAPPS] Refactoring & bugfixes
[reactos.git] / reactos / base / applications / rapps / installed.cpp
1 /*
2 * PROJECT: ReactOS Applications Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/rapps/installed.cpp
5 * PURPOSE: Functions for working with installed applications
6 * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
7 * Alexander Shaposhnikov (chaez.san@gmail.com)
8 */
9
10 #include "rapps.h"
11
12 BOOL
13 GetApplicationString(HKEY hKey, LPCWSTR lpKeyName, ATL::CStringW& String)
14 {
15 BOOL result = GetApplicationString(hKey, lpKeyName, String.GetBuffer(MAX_PATH));
16 String.ReleaseBuffer();
17 return result;
18 }
19
20 BOOL
21 GetApplicationString(HKEY hKey, LPCWSTR lpKeyName, LPWSTR szString)
22 {
23 DWORD dwSize = MAX_PATH * sizeof(WCHAR);
24
25 if (RegQueryValueExW(hKey,
26 lpKeyName,
27 NULL,
28 NULL,
29 (LPBYTE) szString,
30 &dwSize) == ERROR_SUCCESS)
31 {
32 return TRUE;
33 }
34
35 StringCchCopyW(szString, MAX_PATH, L"---");
36 return FALSE;
37 }
38
39 BOOL
40 GetInstalledVersion_WowUser(_Out_opt_ ATL::CStringW* szVersionResult,
41 _In_z_ const ATL::CStringW& RegName,
42 _In_ BOOL IsUserKey,
43 _In_ REGSAM keyWow)
44 {
45 HKEY hKey;
46 BOOL bHasSucceded = FALSE;
47 ATL::CStringW szVersion;
48 ATL::CStringW szPath = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + RegName;
49
50 if (RegOpenKeyExW(IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
51 szPath.GetString(), 0, keyWow | KEY_READ,
52 &hKey) == ERROR_SUCCESS)
53 {
54 if (szVersionResult != NULL)
55 {
56 DWORD dwSize = MAX_PATH * sizeof(WCHAR);
57 DWORD dwType = REG_SZ;
58 if (RegQueryValueExW(hKey,
59 L"DisplayVersion",
60 NULL,
61 &dwType,
62 (LPBYTE) szVersion.GetBuffer(MAX_PATH),
63 &dwSize) == ERROR_SUCCESS)
64 {
65 szVersion.ReleaseBuffer();
66 *szVersionResult = szVersion;
67 bHasSucceded = TRUE;
68 }
69 else
70 {
71 szVersion.ReleaseBuffer();
72 }
73 }
74 else
75 {
76 bHasSucceded = TRUE;
77 szVersion.ReleaseBuffer();
78 }
79
80 }
81
82 RegCloseKey(hKey);
83 return bHasSucceded;
84 }
85
86 BOOL GetInstalledVersion(ATL::CStringW* pszVersion, const ATL::CStringW& szRegName)
87 {
88 return (!szRegName.IsEmpty()
89 && (::GetInstalledVersion_WowUser(pszVersion, szRegName, TRUE, KEY_WOW64_32KEY)
90 || ::GetInstalledVersion_WowUser(pszVersion, szRegName, FALSE, KEY_WOW64_32KEY)
91 || ::GetInstalledVersion_WowUser(pszVersion, szRegName, TRUE, KEY_WOW64_64KEY)
92 || ::GetInstalledVersion_WowUser(pszVersion, szRegName, FALSE, KEY_WOW64_64KEY)));
93 }
94
95 BOOL
96 UninstallApplication(INT Index, BOOL bModify)
97 {
98 LPCWSTR szModify = L"ModifyPath";
99 LPCWSTR szUninstall = L"UninstallString";
100 WCHAR szPath[MAX_PATH];
101 WCHAR szAppName[MAX_STR_LEN];
102 DWORD dwType, dwSize;
103 INT ItemIndex;
104 LVITEM Item;
105 HKEY hKey;
106 PINSTALLED_INFO ItemInfo;
107
108 if (!IS_INSTALLED_ENUM(SelectedEnumType))
109 return FALSE;
110
111 if (Index == -1)
112 {
113 ItemIndex = (INT) SendMessageW(hListView, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
114 if (ItemIndex == -1)
115 return FALSE;
116 }
117 else
118 {
119 ItemIndex = Index;
120 }
121
122 ListView_GetItemText(hListView, ItemIndex, 0, szAppName, _countof(szAppName));
123 WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_REMOVE, szAppName);
124
125 ZeroMemory(&Item, sizeof(Item));
126
127 Item.mask = LVIF_PARAM;
128 Item.iItem = ItemIndex;
129 if (!ListView_GetItem(hListView, &Item))
130 return FALSE;
131
132 ItemInfo = (PINSTALLED_INFO) Item.lParam;
133 hKey = ItemInfo->hSubKey;
134
135 dwType = REG_SZ;
136 dwSize = MAX_PATH * sizeof(WCHAR);
137 if (RegQueryValueExW(hKey,
138 bModify ? szModify : szUninstall,
139 NULL,
140 &dwType,
141 (LPBYTE) szPath,
142 &dwSize) != ERROR_SUCCESS)
143 {
144 return FALSE;
145 }
146
147 return StartProcess(szPath, TRUE);
148 }
149
150
151 BOOL
152 ShowInstalledAppInfo(INT Index)
153 {
154 ATL::CStringW szText;
155 ATL::CStringW szInfo;
156 PINSTALLED_INFO Info = (PINSTALLED_INFO) ListViewGetlParam(Index);
157
158 if (!Info || !Info->hSubKey) return FALSE;
159
160 GetApplicationString(Info->hSubKey, L"DisplayName", szText);
161 NewRichEditText(szText, CFE_BOLD);
162 InsertRichEditText(L"\n", 0);
163
164 #define GET_INFO(a, b, c, d) \
165 if (GetApplicationString(Info->hSubKey, a, szInfo)) \
166 { \
167 szText.LoadStringW(hInst, b); \
168 InsertRichEditText(szText, c); \
169 InsertRichEditText(szInfo, d); \
170 } \
171
172 GET_INFO(L"DisplayVersion", IDS_INFO_VERSION, CFE_BOLD, 0);
173 GET_INFO(L"Publisher", IDS_INFO_PUBLISHER, CFE_BOLD, 0);
174 GET_INFO(L"RegOwner", IDS_INFO_REGOWNER, CFE_BOLD, 0);
175 GET_INFO(L"ProductID", IDS_INFO_PRODUCTID, CFE_BOLD, 0);
176 GET_INFO(L"HelpLink", IDS_INFO_HELPLINK, CFE_BOLD, CFM_LINK);
177 GET_INFO(L"HelpTelephone", IDS_INFO_HELPPHONE, CFE_BOLD, 0);
178 GET_INFO(L"Readme", IDS_INFO_README, CFE_BOLD, 0);
179 GET_INFO(L"Contact", IDS_INFO_CONTACT, CFE_BOLD, 0);
180 GET_INFO(L"URLUpdateInfo", IDS_INFO_UPDATEINFO, CFE_BOLD, CFM_LINK);
181 GET_INFO(L"URLInfoAbout", IDS_INFO_INFOABOUT, CFE_BOLD, CFM_LINK);
182 GET_INFO(L"Comments", IDS_INFO_COMMENTS, CFE_BOLD, 0);
183 GET_INFO(L"InstallDate", IDS_INFO_INSTALLDATE, CFE_BOLD, 0);
184 GET_INFO(L"InstallLocation", IDS_INFO_INSTLOCATION, CFE_BOLD, 0);
185 GET_INFO(L"InstallSource", IDS_INFO_INSTALLSRC, CFE_BOLD, 0);
186 GET_INFO(L"UninstallString", IDS_INFO_UNINSTALLSTR, CFE_BOLD, 0);
187 GET_INFO(L"InstallSource", IDS_INFO_INSTALLSRC, CFE_BOLD, 0);
188 GET_INFO(L"ModifyPath", IDS_INFO_MODIFYPATH, CFE_BOLD, 0);
189
190 return TRUE;
191 }
192
193
194 VOID
195 RemoveAppFromRegistry(INT Index)
196 {
197 PINSTALLED_INFO Info;
198 WCHAR szFullName[MAX_PATH] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
199 ATL::CStringW szMsgText, szMsgTitle;
200 INT ItemIndex = SendMessage(hListView, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
201
202 if (!IS_INSTALLED_ENUM(SelectedEnumType))
203 return;
204
205 Info = (PINSTALLED_INFO) ListViewGetlParam(Index);
206 if (!Info || !Info->hSubKey || (ItemIndex == -1)) return;
207
208 if (!szMsgText.LoadStringW(hInst, IDS_APP_REG_REMOVE) ||
209 !szMsgTitle.LoadStringW(hInst, IDS_INFORMATION))
210 return;
211
212 if (MessageBoxW(hMainWnd, szMsgText, szMsgTitle, MB_YESNO | MB_ICONQUESTION) == IDYES)
213 {
214 ATL::CStringW::CopyChars(szFullName,
215 MAX_PATH,
216 Info->szKeyName.GetString(),
217 MAX_PATH - wcslen(szFullName));
218
219 if (RegDeleteKeyW(Info->hRootKey, szFullName) == ERROR_SUCCESS)
220 {
221 ListView_DeleteItem(hListView, ItemIndex);
222 return;
223 }
224
225 if (!szMsgText.LoadStringW(hInst, IDS_UNABLE_TO_REMOVE))
226 return;
227
228 MessageBoxW(hMainWnd, szMsgText.GetString(), NULL, MB_OK | MB_ICONERROR);
229 }
230 }
231
232
233 BOOL
234 EnumInstalledApplications(INT EnumType, BOOL IsUserKey, APPENUMPROC lpEnumProc)
235 {
236 DWORD dwSize = MAX_PATH, dwType, dwValue;
237 BOOL bIsSystemComponent, bIsUpdate;
238 ATL::CStringW szParentKeyName;
239 ATL::CStringW szDisplayName;
240 INSTALLED_INFO Info;
241 HKEY hKey;
242 LONG ItemIndex = 0;
243
244 Info.hRootKey = IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
245
246 if (RegOpenKeyW(Info.hRootKey,
247 L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
248 &hKey) != ERROR_SUCCESS)
249 {
250 return FALSE;
251 }
252
253 while (RegEnumKeyExW(hKey, ItemIndex, Info.szKeyName.GetBuffer(MAX_PATH), &dwSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
254 {
255 Info.szKeyName.ReleaseBuffer();
256 if (RegOpenKeyW(hKey, Info.szKeyName.GetString(), &Info.hSubKey) == ERROR_SUCCESS)
257 {
258 dwType = REG_DWORD;
259 dwSize = sizeof(DWORD);
260
261 if (RegQueryValueExW(Info.hSubKey,
262 L"SystemComponent",
263 NULL,
264 &dwType,
265 (LPBYTE) &dwValue,
266 &dwSize) == ERROR_SUCCESS)
267 {
268 bIsSystemComponent = (dwValue == 0x1);
269 }
270 else
271 {
272 bIsSystemComponent = FALSE;
273 }
274
275 dwType = REG_SZ;
276 dwSize = MAX_PATH * sizeof(WCHAR);
277 bIsUpdate = (RegQueryValueExW(Info.hSubKey,
278 L"ParentKeyName",
279 NULL,
280 &dwType,
281 (LPBYTE) szParentKeyName.GetBuffer(MAX_PATH),
282 &dwSize) == ERROR_SUCCESS);
283 szParentKeyName.ReleaseBuffer();
284
285 dwType = REG_SZ;
286 dwSize = MAX_PATH * sizeof(WCHAR);
287 if (RegQueryValueExW(Info.hSubKey,
288 L"DisplayName",
289 NULL,
290 &dwType,
291 (LPBYTE) szDisplayName.GetBuffer(MAX_PATH),
292 &dwSize) == ERROR_SUCCESS)
293 {
294 szDisplayName.ReleaseBuffer();
295 if (EnumType < ENUM_ALL_COMPONENTS || EnumType > ENUM_UPDATES)
296 EnumType = ENUM_ALL_COMPONENTS;
297
298 if (!bIsSystemComponent)
299 {
300 if ((EnumType == ENUM_ALL_COMPONENTS) || /* All components */
301 ((EnumType == ENUM_APPLICATIONS) && (!bIsUpdate)) || /* Applications only */
302 ((EnumType == ENUM_UPDATES) && (bIsUpdate))) /* Updates only */
303 {
304 if (!lpEnumProc(ItemIndex, szDisplayName, &Info))
305 break;
306 }
307 else
308 {
309 RegCloseKey(Info.hSubKey);
310 }
311 }
312 else
313 {
314 RegCloseKey(Info.hSubKey);
315 }
316 }
317 else
318 {
319 szDisplayName.ReleaseBuffer();
320 RegCloseKey(Info.hSubKey);
321 }
322 }
323
324 dwSize = MAX_PATH;
325 ItemIndex++;
326 }
327
328 Info.szKeyName.ReleaseBuffer();
329 RegCloseKey(hKey);
330
331 return TRUE;
332 }