ReactOS  0.4.15-dev-2703-g05fb0f1
installed.cpp
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Applications Manager
3  * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE: Classes for working with installed applications
5  * COPYRIGHT: Copyright 2009 Dmitry Chapyshev (dmitry@reactos.org)
6  * Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org)
7  * Copyright 2020 He Yang (1160386205@qq.com)
8  */
9 #include "rapps.h"
10 
11 #include "installed.h"
12 
13 #include "misc.h"
14 
16  : IsUserKey(bIsUserKey), WowKey(RegWowKey), hSubKey(hKey)
17 {
18  // if Initialize failed, hSubKey will be closed automatically and set to zero
19 
20  DWORD dwSize = MAX_PATH, dwType, dwValue;
21  BOOL bIsSystemComponent;
22  ATL::CStringW szParentKeyName;
23 
24  dwType = REG_DWORD;
25  dwSize = sizeof(DWORD);
26 
28  L"SystemComponent",
29  NULL,
30  &dwType,
31  (LPBYTE)&dwValue,
32  &dwSize) == ERROR_SUCCESS)
33  {
34  bIsSystemComponent = (dwValue == 0x1);
35  }
36  else
37  {
38  bIsSystemComponent = FALSE;
39  }
40 
41  dwType = REG_SZ;
42  dwSize = MAX_PATH * sizeof(WCHAR);
44  L"ParentKeyName",
45  NULL,
46  &dwType,
47  (LPBYTE)szParentKeyName.GetBuffer(MAX_PATH),
48  &dwSize) == ERROR_SUCCESS);
49  szParentKeyName.ReleaseBuffer();
50 
51  if (bIsSystemComponent)
52  {
54  hSubKey = NULL;
55  }
56 
57 }
58 
60 {
61  if (hSubKey)
62  {
64  hSubKey = NULL;
65  }
66 }
67 
69 {
70  DWORD dwSize = 0;
71  String.Empty();
72  DWORD dwType;
73 
74  // retrieve the size of value first.
76  lpKeyName,
77  NULL,
78  &dwType,
79  NULL,
80  &dwSize) != ERROR_SUCCESS)
81  {
82  return FALSE;
83  }
84 
85  // TODO: I assume the type as REG_SZ. but I think REG_EXPAND_SZ should be handled correctly too.
86  if (dwType != REG_SZ)
87  {
88  return FALSE;
89  }
90 
91  // allocate buffer.
92  // attention: dwSize is size in bytes, and RegQueryValueExW does not guarantee the terminating null character.
93  String.GetBuffer(dwSize + sizeof(WCHAR));
94 
95  // query the value
97  lpKeyName,
98  NULL,
99  NULL,
100  (LPBYTE)String.GetBuffer(),
101  &dwSize) != ERROR_SUCCESS)
102  {
103  String.ReleaseBuffer();
104  String.Empty();
105  return FALSE;
106  }
107  String.GetBuffer()[dwSize / sizeof(WCHAR)] = L'\0'; // ensure zero terminated
108  String.ReleaseBuffer();
109  return TRUE;
110 }
111 
113 {
114  DWORD dwType = REG_DWORD;
115  DWORD dwSize = sizeof(DWORD);
117  lpKeyName,
118  NULL,
119  &dwType,
120  (LPBYTE)lpValue,
121  &dwSize) != ERROR_SUCCESS)
122  {
123  return FALSE;
124  }
125 
126  return TRUE;
127 }
128 
130 {
131  if (szDisplayIcon.IsEmpty())
132  {
133  return FALSE;
134  }
136  return TRUE;
137 }
138 
140 {
141  if (!bModify)
142  WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_REMOVE, szDisplayName);
143 
144  return StartProcess(bModify ? szModifyPath : szUninstallString, TRUE);
145 }
146 
148 
150 {
151  ATL::CStringW szFullName = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + szKeyName;
152  HMODULE hMod = GetModuleHandleW(L"advapi32.dll");
153  RegDeleteKeyExWProc pRegDeleteKeyExW;
154 
155  // TODO: if there are subkeys inside, simply RegDeleteKeyExW
156  // (or RegDeleteKeyW on Server 2003 SP0 and earlier) will fail
157  // we don't have RegDeleteTree for ReactOS now. (It's a WinVista API)
158  // write a function to delete all subkeys recursively to solve this
159  // or consider letting ReactOS having this API
160 
161  /* Load RegDeleteKeyExW from advapi32.dll if available */
162  if (hMod)
163  {
164  pRegDeleteKeyExW = (RegDeleteKeyExWProc)GetProcAddress(hMod, "RegDeleteKeyExW");
165 
166  if (pRegDeleteKeyExW)
167  {
168  /* Return it */
169  return pRegDeleteKeyExW(IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, szFullName, WowKey, 0);
170  }
171  }
172 
173  /* Otherwise, return non-Ex function */
175 }
176 
178 {
180 
183 
184  int LoopTime;
185 
186  // test if the OS is 64 bit.
187  if (IsSystem64Bit())
188  {
189  // loop for all 3 combination.
190  // note that HKEY_CURRENT_USER\Software don't have a redirect
191  // https://docs.microsoft.com/en-us/windows/win32/winprog64/shared-registry-keys#redirected-shared-and-reflected-keys-under-wow64
192  LoopTime = 3;
193  }
194  else
195  {
196  // loop for 2 combination for KEY_WOW64_32KEY only
197  LoopTime = 2;
198  }
199 
200  // loop for all combination
201  for (int i = 0; i < LoopTime; i++)
202  {
204  HKEY hKey, hSubKey;
205  LONG ItemIndex = 0;
206  ATL::CStringW szKeyName;
207 
208  if (RegOpenKeyExW(RootKeyEnum[i],
209  L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
210  NULL,
211  KEY_READ | RegSamEnum[i],
212  &hKey) != ERROR_SUCCESS)
213  {
214  return FALSE;
215  }
216 
217  while (1)
218  {
219  dwSize = MAX_PATH;
220  if (RegEnumKeyExW(hKey, ItemIndex, szKeyName.GetBuffer(MAX_PATH), &dwSize, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
221  {
222  break;
223  }
224 
225  ItemIndex++;
226 
227  szKeyName.ReleaseBuffer();
228  if (RegOpenKeyW(hKey, szKeyName.GetString(), &hSubKey) == ERROR_SUCCESS)
229  {
230  BOOL bSuccess = FALSE;
231  CInstalledApplicationInfo *Info = new CInstalledApplicationInfo(RootKeyEnum[i] == HKEY_CURRENT_USER, RegSamEnum[i], hSubKey);
232  Info->szKeyName = szKeyName;
233 
234  // check for failure. if failed to init, Info->hSubKey will be set to NULL
235  if (Info->hSubKey)
236  {
237  // those items without display name are ignored
238  if (Info->GetApplicationRegString(L"DisplayName", Info->szDisplayName))
239  {
240  Info->GetApplicationRegString(L"DisplayIcon", Info->szDisplayIcon);
241  Info->GetApplicationRegString(L"DisplayVersion", Info->szDisplayVersion);
242  Info->GetApplicationRegString(L"Publisher", Info->szPublisher);
243  Info->GetApplicationRegString(L"RegOwner", Info->szRegOwner);
244  Info->GetApplicationRegString(L"ProductID", Info->szProductID);
245  Info->GetApplicationRegString(L"HelpLink", Info->szHelpLink);
246  Info->GetApplicationRegString(L"HelpTelephone", Info->szHelpTelephone);
247  Info->GetApplicationRegString(L"Readme", Info->szReadme);
248  Info->GetApplicationRegString(L"Contact", Info->szContact);
249  Info->GetApplicationRegString(L"URLUpdateInfo", Info->szURLUpdateInfo);
250  Info->GetApplicationRegString(L"URLInfoAbout", Info->szURLInfoAbout);
251  Info->GetApplicationRegString(L"Comments", Info->szComments);
252  if (Info->GetApplicationRegString(L"InstallDate", Info->szInstallDate) == FALSE)
253  {
254  // It might be a DWORD (Unix timestamp). try again.
255  DWORD dwInstallTimeStamp;
256  if (Info->GetApplicationRegDword(L"InstallDate", &dwInstallTimeStamp))
257  {
258  FILETIME InstallFileTime;
259  SYSTEMTIME InstallSystemTime, InstallLocalTime;
260 
261  UnixTimeToFileTime(dwInstallTimeStamp, &InstallFileTime);
262  FileTimeToSystemTime(&InstallFileTime, &InstallSystemTime);
263 
264  // convert to localtime
265  SystemTimeToTzSpecificLocalTime(NULL, &InstallSystemTime, &InstallLocalTime);
266 
267  // convert to readable date string
268  int cchTimeStrLen = GetDateFormatW(LOCALE_USER_DEFAULT,
269  0,
270  &InstallLocalTime,
271  NULL, 0, 0);
272 
273  GetDateFormatW(LOCALE_USER_DEFAULT, // use default locale for current user
274  0,
275  &InstallLocalTime,
276  NULL, Info->szInstallDate.GetBuffer(cchTimeStrLen), cchTimeStrLen);
277  Info->szInstallDate.ReleaseBuffer();
278  }
279  }
280  Info->GetApplicationRegString(L"InstallLocation", Info->szInstallLocation);
281  Info->GetApplicationRegString(L"InstallSource", Info->szInstallSource);
282  Info->GetApplicationRegString(L"UninstallString", Info->szUninstallString);
283  Info->GetApplicationRegString(L"ModifyPath", Info->szModifyPath);
284 
285  bSuccess = TRUE;
286  }
287  }
288 
289  // close handle
290  if (Info->hSubKey)
291  {
292  CloseHandle(Info->hSubKey);
293  Info->hSubKey = NULL;
294  }
295 
296  if (bSuccess)
297  {
298  // add to InfoList.
300 
301  // invoke callback
302  if (lpEnumProc)
303  {
304  if ((EnumType == ENUM_ALL_INSTALLED) || /* All components */
305  ((EnumType == ENUM_INSTALLED_APPLICATIONS) && (!Info->bIsUpdate)) || /* Applications only */
306  ((EnumType == ENUM_UPDATES) && (Info->bIsUpdate))) /* Updates only */
307  {
308  lpEnumProc(Info, param);
309  }
310  }
311  }
312  else
313  {
314  // destory object
315  delete Info;
316  }
317  }
318  }
319 
320  szKeyName.ReleaseBuffer();
321  RegCloseKey(hKey);
322  }
323 
324 
325  return TRUE;
326 }
327 
329 {
330  POSITION InfoListPosition = m_InfoList.GetHeadPosition();
331 
332  /* loop and deallocate all the cached app infos in the list */
333  while (InfoListPosition)
334  {
335  CInstalledApplicationInfo *Info = m_InfoList.GetNext(InfoListPosition);
336  delete Info;
337  }
338 
340 }
POSITION GetHeadPosition() const
Definition: atlcoll.h:549
#define CloseHandle
Definition: compat.h:598
#define ERROR_SUCCESS
Definition: deptool.c:10
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define KEY_READ
Definition: nt_native.h:1023
#define TRUE
Definition: types.h:120
#define LOCALE_USER_DEFAULT
#define HKEY_CURRENT_USER
Definition: winreg.h:11
ATL::CStringW szKeyName
Definition: installed.h:14
BOOL IsSystem64Bit()
Definition: misc.cpp:481
BOOL(CALLBACK * APPENUMPROC)(CInstalledApplicationInfo *Info, PVOID param)
Definition: installed.h:45
LONG WINAPI RegDeleteKeyW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey)
Definition: reg.c:1237
#define DWORD
Definition: nt_native.h:44
CInstalledApplicationInfo(BOOL bIsUserKey, REGSAM RegWowKey, HKEY hKey)
Definition: installed.cpp:15
int32_t INT
Definition: typedefs.h:58
BOOL StartProcess(ATL::CStringW &Path, BOOL Wait)
Definition: misc.cpp:121
static BOOLEAN bSuccess
Definition: drive.cpp:432
VOID FreeCachedEntries()
Definition: installed.cpp:328
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:683
BOOL WINAPI SystemTimeToTzSpecificLocalTime(CONST TIME_ZONE_INFORMATION *lpTimeZoneInformation, CONST SYSTEMTIME *lpUniversalTime, LPSYSTEMTIME lpLocalTime)
Definition: timezone.c:377
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:53
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2430
void ReleaseBuffer(_In_ int nNewLength=-1)
Definition: atlsimpstr.h:372
ATL::CStringW szDisplayName
Definition: installed.h:24
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
LONG WINAPI RegOpenKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3296
LSTATUS(WINAPI * RegDeleteKeyExWProc)(HKEY, LPCWSTR, REGSAM, DWORD)
Definition: installed.cpp:147
ATL::CAtlList< CInstalledApplicationInfo * > m_InfoList
Definition: installed.h:49
BOOL Enum(INT EnumType, APPENUMPROC lpEnumProc, PVOID param)
Definition: installed.cpp:177
ATL::CStringW szModifyPath
Definition: installed.h:40
BOOL UninstallApplication(BOOL bModify)
Definition: installed.cpp:139
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
E & GetNext(_Inout_ POSITION &pos)
Definition: atlcoll.h:561
#define EVENTLOG_SUCCESS
Definition: winnt_old.h:2701
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
BOOL WriteLogMessage(WORD wType, DWORD dwEventID, LPCWSTR lpMsg)
Definition: misc.cpp:250
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4116
__wchar_t WCHAR
Definition: xmlstorage.h:180
GLfloat param
Definition: glext.h:5796
#define MAX_PATH
Definition: compat.h:34
#define WINAPI
Definition: msvc.h:6
PCXSTR GetString() const
Definition: atlsimpstr.h:361
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL RetrieveIcon(ATL::CStringW &IconLocation)
Definition: installed.cpp:129
void RemoveAll()
Definition: atlcoll.h:725
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
static const WCHAR L[]
Definition: oid.c:1250
ATL::CStringW szUninstallString
Definition: installed.h:39
INT WINAPI GetDateFormatW(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCWSTR lpFormat, LPWSTR lpDateStr, INT cchOut)
Definition: lcformat.c:979
bool IsEmpty() const
Definition: atlsimpstr.h:379
ATL::CStringW szDisplayIcon
Definition: installed.h:23
POSITION AddTail(INARGTYPE element)
Definition: atlcoll.h:624
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
FxAutoRegKey hKey
ACCESS_MASK REGSAM
Definition: winreg.h:69
BOOL GetApplicationRegString(LPCWSTR lpKeyName, ATL::CStringW &String)
Definition: installed.cpp:68
void UnixTimeToFileTime(DWORD dwUnixTime, LPFILETIME pFileTime)
Definition: misc.cpp:536
#define NULL
Definition: types.h:112
BOOL GetApplicationRegDword(LPCWSTR lpKeyName, DWORD *lpValue)
Definition: installed.cpp:112
HANDLE HKEY
Definition: registry.h:24
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3366
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
#define GetProcAddress(x, y)
Definition: compat.h:612
#define KEY_WOW64_32KEY
Definition: cmtypes.h:45
LONG WINAPI RegEnumKeyExW(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPWSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: reg.c:2527
#define REG_DWORD
Definition: sdbapi.c:596
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define REG_SZ
Definition: layer.c:22