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