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 available applications
5 * COPYRIGHT: Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org)
6 * Copyright 2020 He Yang (1160386205@qq.com)
7 * Copyright 2021-2023 Mark Jansen <mark.jansen@reactos.org>
8 */
9
10 #include "rapps.h"
11 #include "appview.h"
12
CAppInfo(const CStringW & Identifier,AppsCategories Category)13 CAppInfo::CAppInfo(const CStringW &Identifier, AppsCategories Category)
14 : szIdentifier(Identifier), iCategory(Category)
15 {
16 }
17
~CAppInfo()18 CAppInfo::~CAppInfo()
19 {
20 }
21
CAvailableApplicationInfo(CConfigParser * Parser,const CStringW & PkgName,AppsCategories Category,const CPathW & BasePath)22 CAvailableApplicationInfo::CAvailableApplicationInfo(
23 CConfigParser *Parser,
24 const CStringW &PkgName,
25 AppsCategories Category,
26 const CPathW &BasePath)
27 : CAppInfo(PkgName, Category), m_Parser(Parser), m_ScrnshotRetrieved(false), m_LanguagesLoaded(false)
28 {
29 m_Parser->GetString(L"Name", szDisplayName);
30 m_Parser->GetString(L"Version", szDisplayVersion);
31 m_Parser->GetString(L"URLDownload", m_szUrlDownload);
32 m_Parser->GetString(L"Description", szComments);
33
34 CPathW IconPath = BasePath;
35 IconPath += L"icons";
36
37 CStringW IconName;
38 if (m_Parser->GetString(L"Icon", IconName))
39 {
40 IconPath += IconName;
41 }
42 else
43 {
44 // inifile.ico
45 IconPath += (szIdentifier + L".ico");
46 }
47
48 if (PathFileExistsW(IconPath))
49 {
50 szDisplayIcon = (LPCWSTR)IconPath;
51 }
52
53 INT iSizeBytes;
54
55 if (m_Parser->GetInt(L"SizeBytes", iSizeBytes))
56 {
57 StrFormatByteSizeW(iSizeBytes, m_szSize.GetBuffer(MAX_PATH), MAX_PATH);
58 m_szSize.ReleaseBuffer();
59 }
60
61 m_Parser->GetString(L"URLSite", m_szUrlSite);
62 }
63
~CAvailableApplicationInfo()64 CAvailableApplicationInfo::~CAvailableApplicationInfo()
65 {
66 delete m_Parser;
67 }
68
69 VOID
ShowAppInfo(CAppRichEdit * RichEdit)70 CAvailableApplicationInfo::ShowAppInfo(CAppRichEdit *RichEdit)
71 {
72 RichEdit->SetText(szDisplayName, CFE_BOLD);
73 InsertVersionInfo(RichEdit);
74 RichEdit->LoadAndInsertText(IDS_AINFO_LICENSE, LicenseString(), 0);
75 InsertLanguageInfo(RichEdit);
76
77 RichEdit->LoadAndInsertText(IDS_AINFO_SIZE, m_szSize, 0);
78 RichEdit->LoadAndInsertText(IDS_AINFO_URLSITE, m_szUrlSite, CFE_LINK);
79 RichEdit->LoadAndInsertText(IDS_AINFO_DESCRIPTION, szComments, 0);
80 RichEdit->LoadAndInsertText(IDS_AINFO_URLDOWNLOAD, m_szUrlDownload, CFE_LINK);
81 RichEdit->LoadAndInsertText(IDS_AINFO_PACKAGE_NAME, szIdentifier, 0);
82 }
83
84 int
CompareVersion(const CStringW & left,const CStringW & right)85 CompareVersion(const CStringW &left, const CStringW &right)
86 {
87 int nLeft = 0, nRight = 0;
88
89 while (true)
90 {
91 CStringW leftPart = left.Tokenize(L".", nLeft);
92 CStringW rightPart = right.Tokenize(L".", nRight);
93
94 if (leftPart.IsEmpty() && rightPart.IsEmpty())
95 return 0;
96 if (leftPart.IsEmpty())
97 return -1;
98 if (rightPart.IsEmpty())
99 return 1;
100
101 int leftVal, rightVal;
102
103 if (!StrToIntExW(leftPart, STIF_DEFAULT, &leftVal))
104 leftVal = 0;
105 if (!StrToIntExW(rightPart, STIF_DEFAULT, &rightVal))
106 rightVal = 0;
107
108 if (leftVal > rightVal)
109 return 1;
110 if (rightVal < leftVal)
111 return -1;
112 }
113 }
114
115 VOID
InsertVersionInfo(CAppRichEdit * RichEdit)116 CAvailableApplicationInfo::InsertVersionInfo(CAppRichEdit *RichEdit)
117 {
118 CStringW szRegName;
119 m_Parser->GetString(DB_REGNAME, szRegName);
120
121 BOOL bIsInstalled = ::GetInstalledVersion(NULL, szRegName) || ::GetInstalledVersion(NULL, szDisplayName);
122 if (bIsInstalled)
123 {
124 CStringW szInstalledVersion;
125 CStringW szNameVersion = szDisplayName + L" " + szDisplayVersion;
126 BOOL bHasInstalledVersion = ::GetInstalledVersion(&szInstalledVersion, szRegName) ||
127 ::GetInstalledVersion(&szInstalledVersion, szDisplayName) ||
128 ::GetInstalledVersion(&szInstalledVersion, szNameVersion);
129
130 if (bHasInstalledVersion)
131 {
132 BOOL bHasUpdate = CompareVersion(szInstalledVersion, szDisplayVersion) < 0;
133 if (bHasUpdate)
134 {
135 RichEdit->LoadAndInsertText(IDS_STATUS_UPDATE_AVAILABLE, CFE_ITALIC);
136 RichEdit->LoadAndInsertText(IDS_AINFO_VERSION, szInstalledVersion, 0);
137 }
138 else
139 {
140 RichEdit->LoadAndInsertText(IDS_STATUS_INSTALLED, CFE_ITALIC);
141 }
142 }
143 else
144 {
145 RichEdit->LoadAndInsertText(IDS_STATUS_INSTALLED, CFE_ITALIC);
146 }
147 }
148 else
149 {
150 RichEdit->LoadAndInsertText(IDS_STATUS_NOTINSTALLED, CFE_ITALIC);
151 }
152
153 RichEdit->LoadAndInsertText(IDS_AINFO_AVAILABLEVERSION, szDisplayVersion, 0);
154 }
155
156 CStringW
LicenseString()157 CAvailableApplicationInfo::LicenseString()
158 {
159 INT IntBuffer;
160 m_Parser->GetInt(L"LicenseType", IntBuffer);
161 CStringW szLicenseString;
162 m_Parser->GetString(L"License", szLicenseString);
163 LicenseType licenseType;
164
165 if (IsKnownLicenseType(IntBuffer))
166 {
167 licenseType = static_cast<LicenseType>(IntBuffer);
168 }
169 else
170 {
171 licenseType = LICENSE_NONE;
172 if (szLicenseString.CompareNoCase(L"Freeware") == 0)
173 {
174 licenseType = LICENSE_FREEWARE;
175 szLicenseString = L"";
176 }
177 }
178
179 CStringW szLicense;
180 switch (licenseType)
181 {
182 case LICENSE_OPENSOURCE:
183 szLicense.LoadStringW(IDS_LICENSE_OPENSOURCE);
184 break;
185 case LICENSE_FREEWARE:
186 szLicense.LoadStringW(IDS_LICENSE_FREEWARE);
187 break;
188 case LICENSE_TRIAL:
189 szLicense.LoadStringW(IDS_LICENSE_TRIAL);
190 break;
191 default:
192 return szLicenseString;
193 }
194
195 if (!szLicenseString.IsEmpty())
196 szLicense += L" (" + szLicenseString + L")";
197 return szLicense;
198 }
199
200 VOID
InsertLanguageInfo(CAppRichEdit * RichEdit)201 CAvailableApplicationInfo::InsertLanguageInfo(CAppRichEdit *RichEdit)
202 {
203 if (!m_LanguagesLoaded)
204 {
205 RetrieveLanguages();
206 }
207
208 if (m_LanguageLCIDs.GetSize() == 0)
209 {
210 return;
211 }
212
213 const INT nTranslations = m_LanguageLCIDs.GetSize();
214 CStringW szLangInfo;
215 CStringW szLoadedTextAvailability;
216 CStringW szLoadedAInfoText;
217
218 szLoadedAInfoText.LoadStringW(IDS_AINFO_LANGUAGES);
219
220 const LCID lcEnglish = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), SORT_DEFAULT);
221 if (m_LanguageLCIDs.Find(GetUserDefaultLCID()) >= 0)
222 {
223 szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_AVAILABLE_TRANSLATION);
224 if (nTranslations > 1)
225 {
226 CStringW buf;
227 buf.LoadStringW(IDS_LANGUAGE_MORE_PLACEHOLDER);
228 szLangInfo.Format(buf, nTranslations - 1);
229 }
230 else
231 {
232 szLangInfo.LoadStringW(IDS_LANGUAGE_SINGLE);
233 szLangInfo = L" (" + szLangInfo + L")";
234 }
235 }
236 else if (m_LanguageLCIDs.Find(lcEnglish) >= 0)
237 {
238 szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_ENGLISH_TRANSLATION);
239 if (nTranslations > 1)
240 {
241 CStringW buf;
242 buf.LoadStringW(IDS_LANGUAGE_AVAILABLE_PLACEHOLDER);
243 szLangInfo.Format(buf, nTranslations - 1);
244 }
245 else
246 {
247 szLangInfo.LoadStringW(IDS_LANGUAGE_SINGLE);
248 szLangInfo = L" (" + szLangInfo + L")";
249 }
250 }
251 else
252 {
253 szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_NO_TRANSLATION);
254 }
255
256 RichEdit->InsertText(szLoadedAInfoText, CFE_BOLD);
257 RichEdit->InsertText(szLoadedTextAvailability, NULL);
258 RichEdit->InsertText(szLangInfo, CFE_ITALIC);
259 }
260
261 VOID
RetrieveLanguages()262 CAvailableApplicationInfo::RetrieveLanguages()
263 {
264 m_LanguagesLoaded = true;
265
266 CStringW szBuffer;
267 if (!m_Parser->GetString(L"Languages", szBuffer))
268 {
269 return;
270 }
271
272 // Parse parameter string
273 int iIndex = 0;
274 while (true)
275 {
276 CStringW szLocale = szBuffer.Tokenize(L"|", iIndex);
277 if (szLocale.IsEmpty())
278 break;
279
280 szLocale = L"0x" + szLocale;
281
282 INT iLCID;
283 if (StrToIntExW(szLocale, STIF_SUPPORT_HEX, &iLCID))
284 {
285 m_LanguageLCIDs.Add(static_cast<LCID>(iLCID));
286 }
287 }
288 }
289
290 BOOL
Valid() const291 CAvailableApplicationInfo::Valid() const
292 {
293 return !szDisplayName.IsEmpty() && !m_szUrlDownload.IsEmpty();
294 }
295
296 BOOL
CanModify()297 CAvailableApplicationInfo::CanModify()
298 {
299 return FALSE;
300 }
301
302 BOOL
RetrieveIcon(CStringW & Path) const303 CAvailableApplicationInfo::RetrieveIcon(CStringW &Path) const
304 {
305 Path = szDisplayIcon;
306 return !Path.IsEmpty();
307 }
308
309 #define MAX_SCRNSHOT_NUM 16
310 BOOL
RetrieveScreenshot(CStringW & Path)311 CAvailableApplicationInfo::RetrieveScreenshot(CStringW &Path)
312 {
313 if (!m_ScrnshotRetrieved)
314 {
315 static_assert(MAX_SCRNSHOT_NUM < 10000, "MAX_SCRNSHOT_NUM is too big");
316 for (int i = 0; i < MAX_SCRNSHOT_NUM; i++)
317 {
318 CStringW ScrnshotField;
319 ScrnshotField.Format(L"Screenshot%d", i + 1);
320 CStringW ScrnshotLocation;
321 if (!m_Parser->GetString(ScrnshotField, ScrnshotLocation))
322 {
323 // We stop at the first screenshot not found,
324 // so screenshots _have_ to be consecutive
325 break;
326 }
327
328 if (PathIsURLW(ScrnshotLocation.GetString()))
329 {
330 m_szScrnshotLocation.Add(ScrnshotLocation);
331 }
332 }
333 m_ScrnshotRetrieved = true;
334 }
335
336 if (m_szScrnshotLocation.GetSize() > 0)
337 {
338 Path = m_szScrnshotLocation[0];
339 }
340
341 return !Path.IsEmpty();
342 }
343
344 VOID
GetDownloadInfo(CStringW & Url,CStringW & Sha1,ULONG & SizeInBytes) const345 CAvailableApplicationInfo::GetDownloadInfo(CStringW &Url, CStringW &Sha1, ULONG &SizeInBytes) const
346 {
347 Url = m_szUrlDownload;
348 m_Parser->GetString(L"SHA1", Sha1);
349 INT iSizeBytes;
350
351 if (m_Parser->GetInt(L"SizeBytes", iSizeBytes))
352 {
353 SizeInBytes = (ULONG)iSizeBytes;
354 }
355 else
356 {
357 SizeInBytes = 0;
358 }
359 }
360
361 VOID
GetDisplayInfo(CStringW & License,CStringW & Size,CStringW & UrlSite,CStringW & UrlDownload)362 CAvailableApplicationInfo::GetDisplayInfo(CStringW &License, CStringW &Size, CStringW &UrlSite, CStringW &UrlDownload)
363 {
364 License = LicenseString();
365 Size = m_szSize;
366 UrlSite = m_szUrlSite;
367 UrlDownload = m_szUrlDownload;
368 }
369
370 InstallerType
GetInstallerType() const371 CAvailableApplicationInfo::GetInstallerType() const
372 {
373 CStringW str;
374 m_Parser->GetString(DB_INSTALLER, str);
375 if (str.CompareNoCase(DB_GENINSTSECTION) == 0)
376 return INSTALLER_GENERATE;
377 else
378 return INSTALLER_UNKNOWN;
379 }
380
381 BOOL
UninstallApplication(UninstallCommandFlags Flags)382 CAvailableApplicationInfo::UninstallApplication(UninstallCommandFlags Flags)
383 {
384 ATLASSERT(FALSE && "Should not be called");
385 return FALSE;
386 }
387
CInstalledApplicationInfo(HKEY Key,const CStringW & KeyName,AppsCategories Category,UINT KeyInfo)388 CInstalledApplicationInfo::CInstalledApplicationInfo(
389 HKEY Key,
390 const CStringW &KeyName,
391 AppsCategories Category, UINT KeyInfo)
392 : CAppInfo(KeyName, Category), m_hKey(Key), m_KeyInfo(KeyInfo)
393 {
394 if (GetApplicationRegString(L"DisplayName", szDisplayName))
395 {
396 GetApplicationRegString(L"DisplayIcon", szDisplayIcon);
397 GetApplicationRegString(L"DisplayVersion", szDisplayVersion);
398 GetApplicationRegString(L"Comments", szComments);
399 }
400 }
401
~CInstalledApplicationInfo()402 CInstalledApplicationInfo::~CInstalledApplicationInfo()
403 {
404 }
405
406 VOID
AddApplicationRegString(CAppRichEdit * RichEdit,UINT StringID,const CStringW & String,DWORD TextFlags)407 CInstalledApplicationInfo::AddApplicationRegString(
408 CAppRichEdit *RichEdit,
409 UINT StringID,
410 const CStringW &String,
411 DWORD TextFlags)
412 {
413 CStringW Tmp;
414 if (GetApplicationRegString(String, Tmp))
415 {
416 RichEdit->InsertTextWithString(StringID, Tmp, TextFlags);
417 }
418 }
419
420 VOID
ShowAppInfo(CAppRichEdit * RichEdit)421 CInstalledApplicationInfo::ShowAppInfo(CAppRichEdit *RichEdit)
422 {
423 RichEdit->SetText(szDisplayName, CFE_BOLD);
424 RichEdit->InsertText(L"\n", 0);
425
426 RichEdit->InsertTextWithString(IDS_INFO_VERSION, szDisplayVersion, 0);
427 AddApplicationRegString(RichEdit, IDS_INFO_PUBLISHER, L"Publisher", 0);
428 AddApplicationRegString(RichEdit, IDS_INFO_REGOWNER, L"RegOwner", 0);
429 AddApplicationRegString(RichEdit, IDS_INFO_PRODUCTID, L"ProductID", 0);
430 AddApplicationRegString(RichEdit, IDS_INFO_HELPLINK, L"HelpLink", CFM_LINK);
431 AddApplicationRegString(RichEdit, IDS_INFO_HELPPHONE, L"HelpTelephone", 0);
432 AddApplicationRegString(RichEdit, IDS_INFO_README, L"Readme", 0);
433 AddApplicationRegString(RichEdit, IDS_INFO_CONTACT, L"Contact", 0);
434 AddApplicationRegString(RichEdit, IDS_INFO_UPDATEINFO, L"URLUpdateInfo", CFM_LINK);
435 AddApplicationRegString(RichEdit, IDS_INFO_INFOABOUT, L"URLInfoAbout", CFM_LINK);
436 RichEdit->InsertTextWithString(IDS_INFO_COMMENTS, szComments, 0);
437
438 if (m_szInstallDate.IsEmpty())
439 {
440 RetrieveInstallDate();
441 }
442
443 RichEdit->InsertTextWithString(IDS_INFO_INSTALLDATE, m_szInstallDate, 0);
444 AddApplicationRegString(RichEdit, IDS_INFO_INSTLOCATION, L"InstallLocation", 0);
445 AddApplicationRegString(RichEdit, IDS_INFO_INSTALLSRC, L"InstallSource", 0);
446
447 if (m_szUninstallString.IsEmpty())
448 {
449 RetrieveUninstallStrings();
450 }
451
452 RichEdit->InsertTextWithString(IDS_INFO_UNINSTALLSTR, m_szUninstallString, 0);
453 RichEdit->InsertTextWithString(IDS_INFO_MODIFYPATH, m_szModifyString, 0);
454 }
455
456 VOID
RetrieveInstallDate()457 CInstalledApplicationInfo::RetrieveInstallDate()
458 {
459 DWORD dwInstallTimeStamp;
460 SYSTEMTIME InstallLocalTime;
461 if (GetApplicationRegString(L"InstallDate", m_szInstallDate))
462 {
463 ZeroMemory(&InstallLocalTime, sizeof(InstallLocalTime));
464 // Check if we have 8 characters to parse the datetime.
465 // Maybe other formats exist as well?
466 m_szInstallDate = m_szInstallDate.Trim();
467 if (m_szInstallDate.GetLength() == 8)
468 {
469 InstallLocalTime.wYear = wcstol(m_szInstallDate.Left(4).GetString(), NULL, 10);
470 InstallLocalTime.wMonth = wcstol(m_szInstallDate.Mid(4, 2).GetString(), NULL, 10);
471 InstallLocalTime.wDay = wcstol(m_szInstallDate.Mid(6, 2).GetString(), NULL, 10);
472 }
473 }
474 // It might be a DWORD (Unix timestamp). try again.
475 else if (GetApplicationRegDword(L"InstallDate", &dwInstallTimeStamp))
476 {
477 FILETIME InstallFileTime;
478 SYSTEMTIME InstallSystemTime;
479
480 UnixTimeToFileTime(dwInstallTimeStamp, &InstallFileTime);
481 FileTimeToSystemTime(&InstallFileTime, &InstallSystemTime);
482
483 // convert to localtime
484 SystemTimeToTzSpecificLocalTime(NULL, &InstallSystemTime, &InstallLocalTime);
485 }
486
487 // convert to readable date string
488 int cchTimeStrLen = GetDateFormatW(LOCALE_USER_DEFAULT, 0, &InstallLocalTime, NULL, 0, 0);
489
490 GetDateFormatW(
491 LOCALE_USER_DEFAULT, // use default locale for current user
492 0, &InstallLocalTime, NULL, m_szInstallDate.GetBuffer(cchTimeStrLen), cchTimeStrLen);
493 m_szInstallDate.ReleaseBuffer();
494 }
495
496 VOID
RetrieveUninstallStrings()497 CInstalledApplicationInfo::RetrieveUninstallStrings()
498 {
499 DWORD dwWindowsInstaller = 0;
500 if (GetApplicationRegDword(L"WindowsInstaller", &dwWindowsInstaller) && dwWindowsInstaller)
501 {
502 // MSI has the same info in Uninstall / modify, so manually build it
503 m_szUninstallString.Format(L"msiexec /x%s", szIdentifier.GetString());
504 }
505 else
506 {
507 GetApplicationRegString(L"UninstallString", m_szUninstallString);
508 }
509 DWORD dwNoModify = 0;
510 if (!GetApplicationRegDword(L"NoModify", &dwNoModify))
511 {
512 CStringW Tmp;
513 if (GetApplicationRegString(L"NoModify", Tmp))
514 {
515 dwNoModify = Tmp.GetLength() > 0 ? (Tmp[0] == '1') : 0;
516 }
517 else
518 {
519 dwNoModify = 0;
520 }
521 }
522 if (!dwNoModify)
523 {
524 if (dwWindowsInstaller)
525 {
526 m_szModifyString.Format(L"msiexec /i%s", szIdentifier.GetString());
527 }
528 else
529 {
530 GetApplicationRegString(L"ModifyPath", m_szModifyString);
531 }
532 }
533 }
534
535 BOOL
Valid() const536 CInstalledApplicationInfo::Valid() const
537 {
538 return !szDisplayName.IsEmpty();
539 }
540
541 BOOL
CanModify()542 CInstalledApplicationInfo::CanModify()
543 {
544 if (m_szUninstallString.IsEmpty())
545 {
546 RetrieveUninstallStrings();
547 }
548
549 return !m_szModifyString.IsEmpty();
550 }
551
552 BOOL
RetrieveIcon(CStringW & Path) const553 CInstalledApplicationInfo::RetrieveIcon(CStringW &Path) const
554 {
555 Path = szDisplayIcon;
556 return !Path.IsEmpty();
557 }
558
559 BOOL
RetrieveScreenshot(CStringW &)560 CInstalledApplicationInfo::RetrieveScreenshot(CStringW & /*Path*/)
561 {
562 return FALSE;
563 }
564
565 VOID
GetDownloadInfo(CStringW & Url,CStringW & Sha1,ULONG & SizeInBytes) const566 CInstalledApplicationInfo::GetDownloadInfo(CStringW &Url, CStringW &Sha1, ULONG &SizeInBytes) const
567 {
568 ATLASSERT(FALSE && "Should not be called");
569 }
570
571 VOID
GetDisplayInfo(CStringW & License,CStringW & Size,CStringW & UrlSite,CStringW & UrlDownload)572 CInstalledApplicationInfo::GetDisplayInfo(CStringW &License, CStringW &Size, CStringW &UrlSite, CStringW &UrlDownload)
573 {
574 ATLASSERT(FALSE && "Should not be called");
575 }
576
577 InstallerType
GetInstallerType() const578 CInstalledApplicationInfo::GetInstallerType() const
579 {
580 CRegKey reg;
581 if (reg.Open(m_hKey, GENERATE_ARPSUBKEY, KEY_READ) == ERROR_SUCCESS)
582 {
583 return INSTALLER_GENERATE;
584 }
585 return INSTALLER_UNKNOWN;
586 }
587
588 BOOL
UninstallApplication(UninstallCommandFlags Flags)589 CInstalledApplicationInfo::UninstallApplication(UninstallCommandFlags Flags)
590 {
591 if (GetInstallerType() == INSTALLER_GENERATE)
592 {
593 return UninstallGenerated(*this, Flags);
594 }
595
596 BOOL bModify = Flags & UCF_MODIFY;
597 if (m_szUninstallString.IsEmpty())
598 {
599 RetrieveUninstallStrings();
600 }
601
602 CStringW cmd = bModify ? m_szModifyString : m_szUninstallString;
603 if ((Flags & (UCF_MODIFY | UCF_SILENT)) == UCF_SILENT)
604 {
605 DWORD msi = 0;
606 msi = GetApplicationRegDword(L"WindowsInstaller", &msi) && msi;
607 if (msi)
608 {
609 cmd += L" /qn";
610 }
611 else
612 {
613 CStringW silentcmd;
614 if (GetApplicationRegString(L"QuietUninstallString", silentcmd) && !silentcmd.IsEmpty())
615 {
616 cmd = silentcmd;
617 }
618 }
619 }
620
621 BOOL bSuccess = StartProcess(cmd, TRUE);
622
623 if (bSuccess && !bModify)
624 WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_REMOVE, szDisplayName);
625
626 return bSuccess;
627 }
628
629 BOOL
GetApplicationRegString(LPCWSTR lpKeyName,CStringW & String)630 CInstalledApplicationInfo::GetApplicationRegString(LPCWSTR lpKeyName, CStringW &String)
631 {
632 ULONG nChars = 0;
633 // Get the size
634 if (m_hKey.QueryStringValue(lpKeyName, NULL, &nChars) != ERROR_SUCCESS)
635 {
636 String.Empty();
637 return FALSE;
638 }
639
640 LPWSTR Buffer = String.GetBuffer(nChars);
641 LONG lResult = m_hKey.QueryStringValue(lpKeyName, Buffer, &nChars);
642 if (nChars > 0 && Buffer[nChars - 1] == UNICODE_NULL)
643 nChars--;
644 String.ReleaseBuffer(nChars);
645
646 if (lResult != ERROR_SUCCESS)
647 {
648 String.Empty();
649 return FALSE;
650 }
651
652 if (String.Find('%') >= 0)
653 {
654 CStringW Tmp;
655 DWORD dwLen = ExpandEnvironmentStringsW(String, NULL, 0);
656 if (dwLen > 0)
657 {
658 BOOL bSuccess = ExpandEnvironmentStringsW(String, Tmp.GetBuffer(dwLen), dwLen) == dwLen;
659 Tmp.ReleaseBuffer(dwLen - 1);
660 if (bSuccess)
661 {
662 String = Tmp;
663 }
664 else
665 {
666 String.Empty();
667 return FALSE;
668 }
669 }
670 }
671
672 return TRUE;
673 }
674
675 BOOL
GetApplicationRegDword(LPCWSTR lpKeyName,DWORD * lpValue)676 CInstalledApplicationInfo::GetApplicationRegDword(LPCWSTR lpKeyName, DWORD *lpValue)
677 {
678 DWORD dwSize = sizeof(DWORD), dwType;
679 if (RegQueryValueExW(m_hKey, lpKeyName, NULL, &dwType, (LPBYTE)lpValue, &dwSize) != ERROR_SUCCESS ||
680 dwType != REG_DWORD)
681 {
682 return FALSE;
683 }
684
685 return TRUE;
686 }
687