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