Something went wrong. Try again.
Reactos
Something went wrong. Try again.
21 kB · 752 lines
C++
at listview
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753/* * PROJECT: ReactOS Applications Manager * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: Classes for working with available applications * COPYRIGHT: Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org) * Copyright 2020 He Yang (1160386205@qq.com) * Copyright 2021-2023 Mark Jansen <mark.jansen@reactos.org> */
#include "rapps.h"#include "appview.h"
static inline AppsCategoriesClampAvailableCategory(AppsCategories Category){ if (Category <= ENUM_LASTCATEGORY) return Category; return ENUM_CAT_OTHER; // Treat future categories we don't know as Other}
CAppInfo::CAppInfo(const CStringW &Identifier, AppsCategories Category) : szIdentifier(Identifier), iCategory(Category){}
CAppInfo::~CAppInfo(){}
CAvailableApplicationInfo::CAvailableApplicationInfo( CConfigParser *Parser, const CStringW &PkgName, AppsCategories Category, const CPathW &BasePath) : CAppInfo(PkgName, ClampAvailableCategory(Category)), m_Parser(Parser), m_ScrnshotRetrieved(false), m_LanguagesLoaded(false){ m_Parser->GetString(L"Name", szDisplayName); m_Parser->GetString(L"Version", szDisplayVersion); m_Parser->GetString(L"URLDownload", m_szUrlDownload); m_Parser->GetString(L"Description", szComments);
CPathW IconPath = BasePath; IconPath += L"icons";
CStringW IconName; if (m_Parser->GetString(L"Icon", IconName)) { IconPath += IconName; } else { // inifile.ico IconPath += (szIdentifier + L".ico"); }
if (PathFileExistsW(IconPath)) { szDisplayIcon = (LPCWSTR)IconPath; }
INT iSizeBytes;
if (m_Parser->GetInt(L"SizeBytes", iSizeBytes)) { StrFormatByteSizeW(iSizeBytes, m_szSize.GetBuffer(MAX_PATH), MAX_PATH); m_szSize.ReleaseBuffer(); }
m_Parser->GetString(L"URLSite", m_szUrlSite);}
CAvailableApplicationInfo::~CAvailableApplicationInfo(){ delete m_Parser;}
VOIDCAvailableApplicationInfo::ShowAppInfo(CAppRichEdit *RichEdit){ RichEdit->SetText(szDisplayName, CFE_BOLD); InsertVersionInfo(RichEdit); RichEdit->LoadAndInsertText(IDS_AINFO_LICENSE, LicenseString(), 0); InsertLanguageInfo(RichEdit);
RichEdit->LoadAndInsertText(IDS_AINFO_SIZE, m_szSize, 0); RichEdit->LoadAndInsertText(IDS_AINFO_URLSITE, m_szUrlSite, CFE_LINK); RichEdit->LoadAndInsertText(IDS_AINFO_DESCRIPTION, szComments, 0); RichEdit->LoadAndInsertText(IDS_AINFO_URLDOWNLOAD, m_szUrlDownload, CFE_LINK); RichEdit->LoadAndInsertText(IDS_AINFO_PACKAGE_NAME, szIdentifier, 0);}
intCompareVersion(const CStringW &left, const CStringW &right){ int nLeft = 0, nRight = 0;
while (true) { CStringW leftPart = left.Tokenize(L".", nLeft); CStringW rightPart = right.Tokenize(L".", nRight);
if (leftPart.IsEmpty() && rightPart.IsEmpty()) return 0; if (leftPart.IsEmpty()) return -1; if (rightPart.IsEmpty()) return 1;
int leftVal, rightVal;
if (!StrToIntExW(leftPart, STIF_DEFAULT, &leftVal)) leftVal = 0; if (!StrToIntExW(rightPart, STIF_DEFAULT, &rightVal)) rightVal = 0;
if (leftVal > rightVal) return 1; if (rightVal < leftVal) return -1; }}
VOIDCAvailableApplicationInfo::InsertVersionInfo(CAppRichEdit *RichEdit){ CStringW szRegName; m_Parser->GetString(DB_REGNAME, szRegName);
BOOL bIsInstalled = ::GetInstalledVersion(NULL, szRegName) || ::GetInstalledVersion(NULL, szDisplayName); if (bIsInstalled) { CStringW szInstalledVersion; CStringW szNameVersion = szDisplayName + L" " + szDisplayVersion; BOOL bHasInstalledVersion = ::GetInstalledVersion(&szInstalledVersion, szRegName) || ::GetInstalledVersion(&szInstalledVersion, szDisplayName) || ::GetInstalledVersion(&szInstalledVersion, szNameVersion);
if (bHasInstalledVersion) { BOOL bHasUpdate = CompareVersion(szInstalledVersion, szDisplayVersion) < 0; if (bHasUpdate) { RichEdit->LoadAndInsertText(IDS_STATUS_UPDATE_AVAILABLE, CFE_ITALIC); RichEdit->LoadAndInsertText(IDS_AINFO_VERSION, szInstalledVersion, 0); } else { RichEdit->LoadAndInsertText(IDS_STATUS_INSTALLED, CFE_ITALIC); } } else { RichEdit->LoadAndInsertText(IDS_STATUS_INSTALLED, CFE_ITALIC); } } else { RichEdit->LoadAndInsertText(IDS_STATUS_NOTINSTALLED, CFE_ITALIC); }
RichEdit->LoadAndInsertText(IDS_AINFO_AVAILABLEVERSION, szDisplayVersion, 0);}
CStringWCAvailableApplicationInfo::LicenseString(){ INT IntBuffer; m_Parser->GetInt(L"LicenseType", IntBuffer); CStringW szLicenseString; m_Parser->GetString(L"License", szLicenseString); LicenseType licenseType;
if (IsKnownLicenseType(IntBuffer)) licenseType = static_cast<LicenseType>(IntBuffer); else licenseType = LICENSE_NONE;
if (licenseType == LICENSE_NONE || licenseType == LICENSE_FREEWARE) { if (szLicenseString.CompareNoCase(L"Freeware") == 0) { licenseType = LICENSE_FREEWARE; szLicenseString = L""; // Don't display as "Freeware (Freeware)" } }
CStringW szLicense; switch (licenseType) { case LICENSE_OPENSOURCE: szLicense.LoadStringW(IDS_LICENSE_OPENSOURCE); break; case LICENSE_FREEWARE: szLicense.LoadStringW(IDS_LICENSE_FREEWARE); break; case LICENSE_TRIAL: szLicense.LoadStringW(IDS_LICENSE_TRIAL); break; default: return szLicenseString; }
if (!szLicenseString.IsEmpty()) szLicense += L" (" + szLicenseString + L")"; return szLicense;}
VOIDCAvailableApplicationInfo::InsertLanguageInfo(CAppRichEdit *RichEdit){ if (!m_LanguagesLoaded) { RetrieveLanguages(); }
if (m_LanguageLCIDs.GetSize() == 0) { return; }
const INT nTranslations = m_LanguageLCIDs.GetSize(); CStringW szLangInfo; CStringW szLoadedTextAvailability; CStringW szLoadedAInfoText;
szLoadedAInfoText.LoadStringW(IDS_AINFO_LANGUAGES);
const LCID lcEnglish = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), SORT_DEFAULT); if (m_LanguageLCIDs.Find(GetUserDefaultLCID()) >= 0) { szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_AVAILABLE_TRANSLATION); if (nTranslations > 1) { CStringW buf; buf.LoadStringW(IDS_LANGUAGE_MORE_PLACEHOLDER); szLangInfo.Format(buf, nTranslations - 1); } else { szLangInfo.LoadStringW(IDS_LANGUAGE_SINGLE); szLangInfo = L" (" + szLangInfo + L")"; } } else if (m_LanguageLCIDs.Find(lcEnglish) >= 0) { szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_ENGLISH_TRANSLATION); if (nTranslations > 1) { CStringW buf; buf.LoadStringW(IDS_LANGUAGE_AVAILABLE_PLACEHOLDER); szLangInfo.Format(buf, nTranslations - 1); } else { szLangInfo.LoadStringW(IDS_LANGUAGE_SINGLE); szLangInfo = L" (" + szLangInfo + L")"; } } else { szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_NO_TRANSLATION); }
RichEdit->InsertText(szLoadedAInfoText, CFE_BOLD); RichEdit->InsertText(szLoadedTextAvailability, NULL); RichEdit->InsertText(szLangInfo, CFE_ITALIC);}
VOIDCAvailableApplicationInfo::RetrieveLanguages(){ m_LanguagesLoaded = true;
CStringW szBuffer; if (!m_Parser->GetString(L"Languages", szBuffer)) { return; }
// Parse parameter string int iIndex = 0; while (true) { CStringW szLocale = szBuffer.Tokenize(L"|", iIndex); if (szLocale.IsEmpty()) break;
szLocale = L"0x" + szLocale;
INT iLCID; if (StrToIntExW(szLocale, STIF_SUPPORT_HEX, &iLCID)) { m_LanguageLCIDs.Add(static_cast<LCID>(iLCID)); } }}
boolCAvailableApplicationInfo::IsCompatible() const{ CStringW szBuffer; if (m_Parser->GetString(DB_NTVER, szBuffer)) { LPWSTR start = szBuffer.GetString(); LPWSTR p; ULONG MinNTVer = wcstoul(start, &p, 0); if (p > start) { ULONG NTVersion = GetNTVersion(); // Treat as range if we have '-', otherwise treat it as XXX+ ULONG MaxNTVer = (*p == '-') ? wcstoul(++p, NULL, 0) : UINT_MAX; // Handle the XXX- case (That version or lower) if (MaxNTVer == 0) { MaxNTVer = MinNTVer; MinNTVer = 0; }
return NTVersion >= MinNTVer && NTVersion <= MaxNTVer; } } return true;}
BOOLCAvailableApplicationInfo::Valid() const{ return !szDisplayName.IsEmpty() && !m_szUrlDownload.IsEmpty() && IsCompatible();}
BOOLCAvailableApplicationInfo::CanModify(){ return FALSE;}
BOOLCAvailableApplicationInfo::RetrieveIcon(CStringW &Path) const{ Path = szDisplayIcon; return !Path.IsEmpty();}
#define MAX_SCRNSHOT_NUM 16BOOLCAvailableApplicationInfo::RetrieveScreenshot(CStringW &Path){ if (!m_ScrnshotRetrieved) { static_assert(MAX_SCRNSHOT_NUM < 10000, "MAX_SCRNSHOT_NUM is too big"); for (int i = 0; i < MAX_SCRNSHOT_NUM; i++) { CStringW ScrnshotField; ScrnshotField.Format(L"Screenshot%d", i + 1); CStringW ScrnshotLocation; if (!m_Parser->GetString(ScrnshotField, ScrnshotLocation)) { // We stop at the first screenshot not found, // so screenshots _have_ to be consecutive break; }
if (PathIsURLW(ScrnshotLocation.GetString())) { m_szScrnshotLocation.Add(ScrnshotLocation); } } m_ScrnshotRetrieved = true; }
if (m_szScrnshotLocation.GetSize() > 0) { Path = m_szScrnshotLocation[0]; }
return !Path.IsEmpty();}
VOIDCAvailableApplicationInfo::GetDownloadInfo(CStringW &Url, CStringW &Sha1, ULONG &SizeInBytes) const{ Url = m_szUrlDownload; m_Parser->GetString(L"SHA1", Sha1); INT iSizeBytes;
if (m_Parser->GetInt(L"SizeBytes", iSizeBytes)) { SizeInBytes = (ULONG)iSizeBytes; } else { SizeInBytes = 0; }}
VOIDCAvailableApplicationInfo::GetDisplayInfo(CStringW &License, CStringW &Size, CStringW &UrlSite, CStringW &UrlDownload){ License = LicenseString(); Size = m_szSize; UrlSite = m_szUrlSite; UrlDownload = m_szUrlDownload;}
static InstallerTypeGetInstallerTypeFromString(const CStringW &Installer){ if (Installer.CompareNoCase(L"Inno") == 0) return INSTALLER_INNO; if (Installer.CompareNoCase(L"NSIS") == 0) return INSTALLER_NSIS; return INSTALLER_UNKNOWN;}
InstallerTypeCAvailableApplicationInfo::GetInstallerType(bool NestedType) const{ CStringW str; m_Parser->GetString(DB_INSTALLER, str); if (str.CompareNoCase(DB_INSTALLER_GENERATE) == 0) { return INSTALLER_GENERATE; } else if (str.CompareNoCase(DB_INSTALLER_EXEINZIP) == 0) { if (NestedType) { CStringW nested; m_Parser->GetSectionString(DB_EXEINZIPSECTION, DB_INSTALLER, nested); InstallerType it = GetInstallerTypeFromString(nested); if (it != INSTALLER_UNKNOWN) return it; } return INSTALLER_EXEINZIP; } return INSTALLER_UNKNOWN;}
InstallerTypeCAvailableApplicationInfo::GetInstallerInfo(CStringW &SilentParameters) const{ InstallerType it = GetInstallerType(true); m_Parser->GetString(DB_SILENTARGS, SilentParameters); return it;}
BOOLCAvailableApplicationInfo::UninstallApplication(UninstallCommandFlags Flags){ ATLASSERT(FALSE && "Should not be called"); return FALSE;}
CInstalledApplicationInfo::CInstalledApplicationInfo( HKEY Key, const CStringW &KeyName, AppsCategories Category, UINT KeyInfo) : CAppInfo(KeyName, Category), m_hKey(Key), m_KeyInfo(KeyInfo){ if (GetApplicationRegString(L"DisplayName", szDisplayName)) { GetApplicationRegString(L"DisplayIcon", szDisplayIcon); GetApplicationRegString(L"DisplayVersion", szDisplayVersion); GetApplicationRegString(L"Comments", szComments); }}
CInstalledApplicationInfo::~CInstalledApplicationInfo(){}
VOIDCInstalledApplicationInfo::AddApplicationRegString( CAppRichEdit *RichEdit, UINT StringID, const CStringW &String, DWORD TextFlags){ CStringW Tmp; if (GetApplicationRegString(String, Tmp)) { RichEdit->InsertTextWithString(StringID, Tmp, TextFlags); }}
VOIDCInstalledApplicationInfo::ShowAppInfo(CAppRichEdit *RichEdit){ RichEdit->SetText(szDisplayName, CFE_BOLD); RichEdit->InsertText(L"\n", 0);
RichEdit->InsertTextWithString(IDS_INFO_VERSION, szDisplayVersion, 0); AddApplicationRegString(RichEdit, IDS_INFO_PUBLISHER, L"Publisher", 0); AddApplicationRegString(RichEdit, IDS_INFO_REGOWNER, L"RegOwner", 0); AddApplicationRegString(RichEdit, IDS_INFO_PRODUCTID, L"ProductID", 0); AddApplicationRegString(RichEdit, IDS_INFO_HELPLINK, L"HelpLink", CFM_LINK); AddApplicationRegString(RichEdit, IDS_INFO_HELPPHONE, L"HelpTelephone", 0); AddApplicationRegString(RichEdit, IDS_INFO_README, L"Readme", 0); AddApplicationRegString(RichEdit, IDS_INFO_CONTACT, L"Contact", 0); AddApplicationRegString(RichEdit, IDS_INFO_UPDATEINFO, L"URLUpdateInfo", CFM_LINK); AddApplicationRegString(RichEdit, IDS_INFO_INFOABOUT, L"URLInfoAbout", CFM_LINK); RichEdit->InsertTextWithString(IDS_INFO_COMMENTS, szComments, 0);
if (m_szInstallDate.IsEmpty()) { RetrieveInstallDate(); }
RichEdit->InsertTextWithString(IDS_INFO_INSTALLDATE, m_szInstallDate, 0); AddApplicationRegString(RichEdit, IDS_INFO_INSTLOCATION, L"InstallLocation", 0); AddApplicationRegString(RichEdit, IDS_INFO_INSTALLSRC, L"InstallSource", 0);
if (m_szUninstallString.IsEmpty()) { RetrieveUninstallStrings(); }
RichEdit->InsertTextWithString(IDS_INFO_UNINSTALLSTR, m_szUninstallString, 0); RichEdit->InsertTextWithString(IDS_INFO_MODIFYPATH, m_szModifyString, 0);}
VOIDCInstalledApplicationInfo::RetrieveInstallDate(){ DWORD dwInstallTimeStamp; SYSTEMTIME InstallLocalTime; if (GetApplicationRegString(L"InstallDate", m_szInstallDate)) { ZeroMemory(&InstallLocalTime, sizeof(InstallLocalTime)); // Check if we have 8 characters to parse the datetime. // Maybe other formats exist as well? m_szInstallDate = m_szInstallDate.Trim(); if (m_szInstallDate.GetLength() == 8) { InstallLocalTime.wYear = wcstol(m_szInstallDate.Left(4).GetString(), NULL, 10); InstallLocalTime.wMonth = wcstol(m_szInstallDate.Mid(4, 2).GetString(), NULL, 10); InstallLocalTime.wDay = wcstol(m_szInstallDate.Mid(6, 2).GetString(), NULL, 10); } } // It might be a DWORD (Unix timestamp). try again. else if (GetApplicationRegDword(L"InstallDate", &dwInstallTimeStamp)) { FILETIME InstallFileTime; SYSTEMTIME InstallSystemTime;
UnixTimeToFileTime(dwInstallTimeStamp, &InstallFileTime); FileTimeToSystemTime(&InstallFileTime, &InstallSystemTime);
// convert to localtime SystemTimeToTzSpecificLocalTime(NULL, &InstallSystemTime, &InstallLocalTime); }
// convert to readable date string int cchTimeStrLen = GetDateFormatW(LOCALE_USER_DEFAULT, 0, &InstallLocalTime, NULL, 0, 0);
GetDateFormatW( LOCALE_USER_DEFAULT, // use default locale for current user 0, &InstallLocalTime, NULL, m_szInstallDate.GetBuffer(cchTimeStrLen), cchTimeStrLen); m_szInstallDate.ReleaseBuffer();}
VOIDCInstalledApplicationInfo::RetrieveUninstallStrings(){ DWORD dwWindowsInstaller = 0; if (GetApplicationRegDword(L"WindowsInstaller", &dwWindowsInstaller) && dwWindowsInstaller) { // MSI has the same info in Uninstall / modify, so manually build it m_szUninstallString.Format(L"msiexec /x%s", szIdentifier.GetString()); } else { GetApplicationRegString(L"UninstallString", m_szUninstallString); } DWORD dwNoModify = 0; if (!GetApplicationRegDword(L"NoModify", &dwNoModify)) { CStringW Tmp; if (GetApplicationRegString(L"NoModify", Tmp)) { dwNoModify = Tmp.GetLength() > 0 ? (Tmp[0] == '1') : 0; } else { dwNoModify = 0; } } if (!dwNoModify) { if (dwWindowsInstaller) { m_szModifyString.Format(L"msiexec /i%s", szIdentifier.GetString()); } else { GetApplicationRegString(L"ModifyPath", m_szModifyString); } }}
BOOLCInstalledApplicationInfo::Valid() const{ return !szDisplayName.IsEmpty();}
BOOLCInstalledApplicationInfo::CanModify(){ if (m_szUninstallString.IsEmpty()) { RetrieveUninstallStrings(); }
return !m_szModifyString.IsEmpty();}
BOOLCInstalledApplicationInfo::RetrieveIcon(CStringW &Path) const{ Path = szDisplayIcon; return !Path.IsEmpty();}
BOOLCInstalledApplicationInfo::RetrieveScreenshot(CStringW & /*Path*/){ return FALSE;}
VOIDCInstalledApplicationInfo::GetDownloadInfo(CStringW &Url, CStringW &Sha1, ULONG &SizeInBytes) const{ ATLASSERT(FALSE && "Should not be called");}
VOIDCInstalledApplicationInfo::GetDisplayInfo(CStringW &License, CStringW &Size, CStringW &UrlSite, CStringW &UrlDownload){ ATLASSERT(FALSE && "Should not be called");}
InstallerTypeCInstalledApplicationInfo::GetInstallerType(bool NestedType) const{ CRegKey reg; if (reg.Open(m_hKey, GENERATE_ARPSUBKEY, KEY_READ) == ERROR_SUCCESS) { return INSTALLER_GENERATE; } return INSTALLER_UNKNOWN;}
BOOLCInstalledApplicationInfo::UninstallApplication(UninstallCommandFlags Flags){ if (GetInstallerType() == INSTALLER_GENERATE && (Flags & UCF_SAMEPROCESS)) { return UninstallGenerated(*this, Flags); }
BOOL bModify = Flags & UCF_MODIFY; if (m_szUninstallString.IsEmpty()) { RetrieveUninstallStrings(); }
CStringW cmd = bModify ? m_szModifyString : m_szUninstallString; if ((Flags & (UCF_MODIFY | UCF_SILENT)) == UCF_SILENT) { DWORD msi = 0; msi = GetApplicationRegDword(L"WindowsInstaller", &msi) && msi; if (msi) { cmd += L" /qn"; } else { CStringW silentcmd; if (GetApplicationRegString(L"QuietUninstallString", silentcmd) && !silentcmd.IsEmpty()) { cmd = silentcmd; } } }
BOOL bSuccess = StartProcess(cmd, TRUE);
if (bSuccess && !bModify) WriteLogMessage(EVENTLOG_SUCCESS, MSG_SUCCESS_REMOVE, szDisplayName);
return bSuccess;}
BOOLCInstalledApplicationInfo::GetApplicationRegString(LPCWSTR lpKeyName, CStringW &String){ ULONG nChars = 0; // Get the size if (m_hKey.QueryStringValue(lpKeyName, NULL, &nChars) != ERROR_SUCCESS) { String.Empty(); return FALSE; }
LPWSTR Buffer = String.GetBuffer(nChars); LONG lResult = m_hKey.QueryStringValue(lpKeyName, Buffer, &nChars); if (nChars > 0 && Buffer[nChars - 1] == UNICODE_NULL) nChars--; String.ReleaseBuffer(nChars);
if (lResult != ERROR_SUCCESS) { String.Empty(); return FALSE; }
if (String.Find('%') >= 0) { CStringW Tmp; DWORD dwLen = ExpandEnvironmentStringsW(String, NULL, 0); if (dwLen > 0) { BOOL bSuccess = ExpandEnvironmentStringsW(String, Tmp.GetBuffer(dwLen), dwLen) == dwLen; Tmp.ReleaseBuffer(dwLen - 1); if (bSuccess) { String = Tmp; } else { String.Empty(); return FALSE; } } }
return TRUE;}
BOOLCInstalledApplicationInfo::GetApplicationRegDword(LPCWSTR lpKeyName, DWORD *lpValue){ DWORD dwSize = sizeof(DWORD), dwType; if (RegQueryValueExW(m_hKey, lpKeyName, NULL, &dwType, (LPBYTE)lpValue, &dwSize) != ERROR_SUCCESS || dwType != REG_DWORD) { return FALSE; }
return TRUE;}