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