ReactOS  0.4.15-dev-4870-g846c9aa
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  * Copyright 2021 Mark Jansen <mark.jansen@reactos.org>
9  */
10 
11 #include "rapps.h"
12 #include "installed.h"
13 #include "misc.h"
14 
16  : m_IsUserKey(bIsUserKey)
17  , m_WowKey(RegWowKey)
18  , m_hSubKey(hKey)
19  , m_szKeyName(szKeyName)
20 {
21  DWORD dwSize = 0;
22  bIsUpdate = (RegQueryValueExW(m_hSubKey, L"ParentKeyName", NULL, NULL, NULL, &dwSize) == ERROR_SUCCESS);
23 }
24 
26 {
27  if (m_hSubKey)
28  {
30  m_hSubKey = NULL;
31  }
32 }
33 
35 {
36  // Key not closed, so we have not loaded details yet
37  if (m_hSubKey)
38  {
43  GetApplicationRegString(L"HelpTelephone", szHelpTelephone);
46  GetApplicationRegString(L"URLUpdateInfo", szURLUpdateInfo);
48 
49  DWORD dwInstallTimeStamp;
50  SYSTEMTIME InstallLocalTime;
51  if (GetApplicationRegString(L"InstallDate", szInstallDate))
52  {
53  ZeroMemory(&InstallLocalTime, sizeof(InstallLocalTime));
54  // Check if we have 8 characters to parse the datetime.
55  // Maybe other formats exist as well?
57  if (szInstallDate.GetLength() == 8)
58  {
59  InstallLocalTime.wYear = wcstol(szInstallDate.Left(4).GetString(), NULL, 10);
60  InstallLocalTime.wMonth = wcstol(szInstallDate.Mid(4, 2).GetString(), NULL, 10);
61  InstallLocalTime.wDay = wcstol(szInstallDate.Mid(6, 2).GetString(), NULL, 10);
62  }
63  }
64  // It might be a DWORD (Unix timestamp). try again.
65  else if (GetApplicationRegDword(L"InstallDate", &dwInstallTimeStamp))
66  {
67  FILETIME InstallFileTime;
68  SYSTEMTIME InstallSystemTime;
69 
70  UnixTimeToFileTime(dwInstallTimeStamp, &InstallFileTime);
71  FileTimeToSystemTime(&InstallFileTime, &InstallSystemTime);
72 
73  // convert to localtime
74  SystemTimeToTzSpecificLocalTime(NULL, &InstallSystemTime, &InstallLocalTime);
75  }
76 
77  // convert to readable date string
78  int cchTimeStrLen = GetDateFormatW(LOCALE_USER_DEFAULT, 0, &InstallLocalTime, NULL, 0, 0);
79 
81  LOCALE_USER_DEFAULT, // use default locale for current user
82  0, &InstallLocalTime, NULL, szInstallDate.GetBuffer(cchTimeStrLen), cchTimeStrLen);
84 
85  GetApplicationRegString(L"InstallLocation", szInstallLocation);
86  GetApplicationRegString(L"InstallSource", szInstallSource);
87  DWORD dwWindowsInstaller = 0;
88  if (GetApplicationRegDword(L"WindowsInstaller", &dwWindowsInstaller) && dwWindowsInstaller)
89  {
90  // MSI has the same info in Uninstall / modify, so manually build it
92  }
93  else
94  {
95  GetApplicationRegString(L"UninstallString", szUninstallString);
96  }
97  DWORD dwNoModify = 0;
98  if (!GetApplicationRegDword(L"NoModify", &dwNoModify))
99  {
100  CStringW Tmp;
101  if (GetApplicationRegString(L"NoModify", Tmp))
102  {
103  dwNoModify = Tmp.GetLength() > 0 ? (Tmp[0] == '1') : 0;
104  }
105  else
106  {
107  dwNoModify = 0;
108  }
109  }
110  if (!dwNoModify)
111  {
112  if (dwWindowsInstaller)
113  {
114  szModifyPath.Format(L"msiexec /i%s", m_szKeyName.GetString());
115  }
116  else
117  {
118  GetApplicationRegString(L"ModifyPath", szModifyPath);
119  }
120  }
121 
123  m_hSubKey = NULL;
124  }
125 }
126 
128 {
129  DWORD dwAllocated = 0, dwSize, dwType;
130 
131  // retrieve the size of value first.
132  if (RegQueryValueExW(m_hSubKey, lpKeyName, NULL, &dwType, NULL, &dwAllocated) != ERROR_SUCCESS)
133  {
134  String.Empty();
135  return FALSE;
136  }
137 
138  if (dwType != REG_SZ && dwType != REG_EXPAND_SZ)
139  {
140  String.Empty();
141  return FALSE;
142  }
143 
144  // query the value
145  dwSize = dwAllocated;
146  LSTATUS Result =
147  RegQueryValueExW(m_hSubKey, lpKeyName, NULL, NULL, (LPBYTE)String.GetBuffer(dwAllocated / sizeof(WCHAR)), &dwSize);
148 
149  dwSize = min(dwAllocated, dwSize);
150  // CString takes care of zero-terminating it
151  String.ReleaseBuffer(dwSize / sizeof(WCHAR));
152 
153  if (Result != ERROR_SUCCESS)
154  {
155  String.Empty();
156  return FALSE;
157  }
158 
159  if (dwType == REG_EXPAND_SZ)
160  {
161  CStringW Tmp;
162 
164  if (dwLen > 0)
165  {
166  BOOL bSuccess = ExpandEnvironmentStringsW(String, Tmp.GetBuffer(dwLen), dwLen) == dwLen;
167  Tmp.ReleaseBuffer(dwLen - 1);
168  if (bSuccess)
169  {
170  String = Tmp;
171  }
172  else
173  {
174  String.Empty();
175  return FALSE;
176  }
177  }
178  }
179 
180  return TRUE;
181 }
182 
184 {
185  DWORD dwSize = sizeof(DWORD), dwType;
187  lpKeyName,
188  NULL,
189  &dwType,
190  (LPBYTE)lpValue,
191  &dwSize) != ERROR_SUCCESS || dwType != REG_DWORD)
192  {
193  return FALSE;
194  }
195 
196  return TRUE;
197 }
198 
200 {
201  if (szDisplayIcon.IsEmpty())
202  {
203  return FALSE;
204  }
206  return TRUE;
207 }
208 
210 {
211  if (!bModify)
212  WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_REMOVE, szDisplayName);
213 
214  return StartProcess(bModify ? szModifyPath : szUninstallString, TRUE);
215 }
216 
218 
220 {
221  ATL::CStringW szFullName = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + m_szKeyName;
222  HMODULE hMod = GetModuleHandleW(L"advapi32.dll");
223  RegDeleteKeyExWProc pRegDeleteKeyExW;
224 
225  // TODO: if there are subkeys inside, simply RegDeleteKeyExW
226  // (or RegDeleteKeyW on Server 2003 SP0 and earlier) will fail
227  // we don't have RegDeleteTree for ReactOS now. (It's a WinVista API)
228  // write a function to delete all subkeys recursively to solve this
229  // or consider letting ReactOS having this API
230 
231  /* Load RegDeleteKeyExW from advapi32.dll if available */
232  if (hMod)
233  {
234  pRegDeleteKeyExW = (RegDeleteKeyExWProc)GetProcAddress(hMod, "RegDeleteKeyExW");
235 
236  if (pRegDeleteKeyExW)
237  {
238  /* Return it */
239  return pRegDeleteKeyExW(m_IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, szFullName, m_WowKey, 0);
240  }
241  }
242 
243  /* Otherwise, return non-Ex function */
245 }
246 
248 {
250 
253 
254  int LoopTime;
255 
256  // test if the OS is 64 bit.
257  if (IsSystem64Bit())
258  {
259  // loop for all 3 combination.
260  // note that HKEY_CURRENT_USER\Software don't have a redirect
261  // https://docs.microsoft.com/en-us/windows/win32/winprog64/shared-registry-keys#redirected-shared-and-reflected-keys-under-wow64
262  LoopTime = 3;
263  }
264  else
265  {
266  // loop for 2 combination for KEY_WOW64_32KEY only
267  LoopTime = 2;
268  }
269 
270  // loop for all combination
271  for (int i = 0; i < LoopTime; i++)
272  {
274  HKEY hKey, hSubKey;
275  LONG ItemIndex = 0;
276  ATL::CStringW szKeyName;
277 
278  if (RegOpenKeyExW(RootKeyEnum[i],
279  L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
280  NULL,
281  KEY_READ | RegSamEnum[i],
282  &hKey) != ERROR_SUCCESS)
283  {
284  return FALSE;
285  }
286 
287  while (1)
288  {
289  dwSize = MAX_PATH;
290  if (RegEnumKeyExW(hKey, ItemIndex, szKeyName.GetBuffer(MAX_PATH), &dwSize, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
291  {
292  break;
293  }
294 
295  ItemIndex++;
296 
297  szKeyName.ReleaseBuffer();
298  if (RegOpenKeyW(hKey, szKeyName, &hSubKey) == ERROR_SUCCESS)
299  {
300  DWORD dwValue = 0;
301  BOOL bIsSystemComponent = FALSE;
302 
303  dwSize = sizeof(DWORD);
304  if (RegQueryValueExW(hSubKey, L"SystemComponent", NULL, NULL, (LPBYTE)&dwValue, &dwSize) == ERROR_SUCCESS)
305  {
306  bIsSystemComponent = (dwValue == 0x1);
307  }
308  // Ignore system components
309  if (bIsSystemComponent)
310  {
311  RegCloseKey(hSubKey);
312  continue;
313  }
314 
315  BOOL bSuccess = FALSE;
316  CInstalledApplicationInfo *Info = new CInstalledApplicationInfo(RootKeyEnum[i] == HKEY_CURRENT_USER, RegSamEnum[i], hSubKey, szKeyName);
317 
318  // items without display name are ignored
319  if (Info->GetApplicationRegString(L"DisplayName", Info->szDisplayName))
320  {
321  Info->GetApplicationRegString(L"DisplayIcon", Info->szDisplayIcon);
322  Info->GetApplicationRegString(L"DisplayVersion", Info->szDisplayVersion);
323  Info->GetApplicationRegString(L"Comments", Info->szComments);
324 
325  bSuccess = TRUE;
326  }
327 
328  if (bSuccess)
329  {
330  // add to InfoList.
332 
333  // invoke callback
334  if (lpEnumProc)
335  {
336  if ((EnumType == ENUM_ALL_INSTALLED) || /* All components */
337  ((EnumType == ENUM_INSTALLED_APPLICATIONS) && (!Info->bIsUpdate)) || /* Applications only */
338  ((EnumType == ENUM_UPDATES) && (Info->bIsUpdate))) /* Updates only */
339  {
340  lpEnumProc(Info, param);
341  }
342  }
343  }
344  else
345  {
346  // destory object
347  delete Info;
348  }
349  }
350  }
351 
352  szKeyName.ReleaseBuffer();
353  RegCloseKey(hKey);
354  }
355 
356  return TRUE;
357 }
358 
360 {
361  POSITION InfoListPosition = m_InfoList.GetHeadPosition();
362 
363  /* loop and deallocate all the cached app infos in the list */
364  while (InfoListPosition)
365  {
366  CInstalledApplicationInfo *Info = m_InfoList.GetNext(InfoListPosition);
367  delete Info;
368  }
369 
371 }
int GetLength() const
Definition: atlsimpstr.h:356
CInstalledApplicationInfo(BOOL bIsUserKey, REGSAM RegWowKey, HKEY hKey, const CStringW &szKeyName)
Definition: installed.cpp:15
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
WORD wMonth
Definition: winbase.h:903
#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
BOOL IsSystem64Bit()
Definition: misc.cpp:339
CStringT Mid(int iFirst, int nCount) const
Definition: cstringt.h:700
BOOL(CALLBACK * APPENUMPROC)(CInstalledApplicationInfo *Info, PVOID param)
Definition: installed.h:52
LONG WINAPI RegDeleteKeyW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey)
Definition: reg.c:1237
#define ZeroMemory
Definition: winbase.h:1667
void __cdecl Format(UINT nFormatID,...)
Definition: cstringt.h:753
_Check_return_ long __cdecl wcstol(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
#define DWORD
Definition: nt_native.h:44
int32_t INT
Definition: typedefs.h:58
static BOOLEAN bSuccess
Definition: drive.cpp:430
VOID FreeCachedEntries()
Definition: installed.cpp:359
_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
WORD wYear
Definition: winbase.h:902
#define L(x)
Definition: ntvdm.h:50
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
#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:3291
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
LSTATUS(WINAPI * RegDeleteKeyExWProc)(HKEY, LPCWSTR, REGSAM, DWORD)
Definition: installed.cpp:217
ATL::CAtlList< CInstalledApplicationInfo * > m_InfoList
Definition: installed.h:56
BOOL Enum(INT EnumType, APPENUMPROC lpEnumProc, PVOID param)
Definition: installed.cpp:247
BOOL UninstallApplication(BOOL bModify)
Definition: installed.cpp:209
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
E & GetNext(_Inout_ POSITION &pos)
Definition: atlcoll.h:561
#define EVENTLOG_SUCCESS
Definition: winnt_old.h:2880
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:226
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4120
__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:199
void RemoveAll()
Definition: atlcoll.h:725
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
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
WORD wDay
Definition: winbase.h:905
POSITION AddTail(INARGTYPE element)
Definition: atlcoll.h:624
BOOL StartProcess(const ATL::CStringW &Path, BOOL Wait)
Definition: misc.cpp:83
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
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
ACCESS_MASK REGSAM
Definition: winreg.h:69
BOOL GetApplicationRegString(LPCWSTR lpKeyName, ATL::CStringW &String)
Definition: installed.cpp:127
#define min(a, b)
Definition: monoChain.cc:55
void UnixTimeToFileTime(DWORD dwUnixTime, LPFILETIME pFileTime)
Definition: misc.cpp:394
#define NULL
Definition: types.h:112
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
BOOL GetApplicationRegDword(LPCWSTR lpKeyName, DWORD *lpValue)
Definition: installed.cpp:183
HANDLE HKEY
Definition: registry.h:26
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3356
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
CStringT & Trim()
Definition: cstringt.h:971
CStringT Left(int nCount) const
Definition: cstringt.h:728
#define RegCloseKey(hKey)
Definition: registry.h:47
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define REG_SZ
Definition: layer.c:22