diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 5e6793a0..e1647871 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -38,7 +38,7 @@ jobs: - name: Clean PanelSwWixExtension (keep extranal code build) run: | Remove-Item ("${{ github.workspace }}" + "\build") -Recurse -Force - nuget restore + nuget restore src/dirs.proj - name: Initialize CodeQL uses: github/codeql-action/init@v2 @@ -46,7 +46,7 @@ jobs: languages: ${{ matrix.language }} - name: Build & scan - run: msbuild dirs.proj -restore -p:DisableNuget=true + run: msbuild src/dirs.proj -restore -p:DisableNuget=true - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/github-actions-build.yml b/.github/workflows/github-actions-build.yml index bee68920..8bbb1c5a 100644 --- a/.github/workflows/github-actions-build.yml +++ b/.github/workflows/github-actions-build.yml @@ -11,7 +11,7 @@ on: psw_wix_version: description: 'PanelSwWix4 version' required: true - default: 5.0.0-psw-wix.0246-34 + default: 5.0.0-psw-wix.0248-35 type: string jobs: @@ -26,7 +26,7 @@ jobs: - name: Resolve build version run: | $xmlDoc = New-Object System.Xml.XmlDocument - $file = [System.IO.Path]::Combine("${{ github.workspace }}", "TidyBuild.custom.props") + $file = [System.IO.Path]::Combine("${{ github.workspace }}", "src", "TidyBuild.custom.props") [xml]$xmlDoc = Get-Content $file $node = $xmlDoc.SelectSingleNode('//*[local-name(.)="FullVersion"]') Add-Content -Path ${{ github.env }} -Value ("FULL_VERSION=" + $node.InnerText + ".${{ github.run_number }}") @@ -37,34 +37,34 @@ jobs: Add-Content -Path ${{ github.env }} -Value "PSW_WIX_VERSION=${{ env.DEFAULT_PSW_WIX_VERSION }}" } env: - DEFAULT_PSW_WIX_VERSION: '5.0.0-psw-wix.0246-34' + DEFAULT_PSW_WIX_VERSION: '5.0.0-psw-wix.0248-35' - name: Prepare for build run: | choco install windows-adk-all dotnet nuget add source --username ${{ github.actor }} --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" - nuget restore + nuget restore src/dirs.proj - name: Build PanelSwWixExtension - run: msbuild dirs.proj -restore -p:FullVersion=${{ env.FULL_VERSION }} + run: msbuild src/dirs.proj -restore -p:FullVersion=${{ env.FULL_VERSION }} - name: Build PanelSwWixExtension with PanelSwWix4 run: | - msbuild dirs.proj -t:WixtoolsetToPanelSwWix4 "-p:PanelSwWix4Version=${{ env.PSW_WIX_VERSION }}" -p:NugetPrereleaseVersion=-psw-wix + msbuild src/dirs.proj -t:WixtoolsetToPanelSwWix4 "-p:PanelSwWix4Version=${{ env.PSW_WIX_VERSION }}" -p:NugetPrereleaseVersion=-psw-wix Remove-Item ("${{ github.workspace }}" + "\build") -Recurse -Force - msbuild dirs.proj -restore -p:FullVersion=${{ env.FULL_VERSION }} "-p:PanelSwWix4Version=${{ env.PSW_WIX_VERSION }}" -p:NugetPrereleaseVersion=-psw-wix + msbuild src/dirs.proj -restore -p:FullVersion=${{ env.FULL_VERSION }} "-p:PanelSwWix4Version=${{ env.PSW_WIX_VERSION }}" -p:NugetPrereleaseVersion=-psw-wix -p:EnableZipContainer=true - uses: actions/upload-artifact@v3.1.2 with: name: nuget - path: nuget-out\*.nupkg + path: src\nuget-out\*.nupkg - name: Publish nuget packages to github and nuget.org if: ${{ github.event.inputs.publish_nuget == 'true' && github.ref == 'refs/heads/master4' }} env: GITHUB_TOKEN: ${{ secrets.TAGGER_PAT }} run: | - dotnet nuget push nuget-out\PanelSwWixExtension4.*.nupkg --api-key ${{ secrets.GITHUB_TOKEN }} --source github - dotnet nuget push nuget-out\PanelSwWixExtension4.*.nupkg --api-key ${{ secrets.NUGET_TOKEN }} --source https://api.nuget.org/v3/index.json + dotnet nuget push src\nuget-out\PanelSwWixExtension4.*.nupkg --api-key ${{ secrets.GITHUB_TOKEN }} --source github + dotnet nuget push src\nuget-out\PanelSwWixExtension4.*.nupkg --api-key ${{ secrets.NUGET_TOKEN }} --source https://api.nuget.org/v3/index.json git tag "wix4-v${{ env.FULL_VERSION }}" git push --tags diff --git a/.gitignore b/.gitignore index 6e07df5e..608f19cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ Debug -/ obj/ bin/ *.sdf @@ -11,7 +10,7 @@ bin/ /nuget-out .vs/ *.ipch -/packages/ +packages/ /build/ /build-common/ *.user.* diff --git a/.gitmodules b/.gitmodules index e09d68e2..d9f7eeb1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,10 +1,13 @@ [submodule "protobuf"] - path = protobuf + path = src/protobuf url = https://github.com/google/protobuf.git branch = 3.5.1.1 [submodule "exprtk"] - path = exprtk + path = src/exprtk url = https://github.com/ArashPartow/exprtk.git [submodule "poco"] - path = poco + path = src/poco url = https://github.com/pocoproject/poco.git +[submodule "7Zap"] + path = src/7Zap + url = https://github.com/nirbar/7Zap.git diff --git a/PanelSwWixExtension/PanelSwBurnContainer.cs b/PanelSwWixExtension/PanelSwBurnContainer.cs deleted file mode 100644 index a1001d2b..00000000 --- a/PanelSwWixExtension/PanelSwBurnContainer.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using WixToolset.Data.Symbols; -using WixToolset.Extensibility; - -namespace PanelSw.Wix.Extensions -{ - public class PanelSwBurnContainer : BaseBurnContainerExtension - { - public override IReadOnlyCollection ContainerExtensionIds => new[] { PanelSwWixExtension.CONTAINER_EXTENSION_ID }; - - public override void CreateContainer(WixBundleContainerSymbol container, IEnumerable containerPayloads, out string sha512, out long size) - { - sha512 = null; - size = 0; - - try - { - if (File.Exists(container.WorkingPath)) - { - File.Delete(container.WorkingPath); - } - using (ZipArchive zipFile = ZipFile.Open(container.WorkingPath, ZipArchiveMode.Create)) - { - foreach (WixBundlePayloadSymbol payload in containerPayloads) - { - string entryName = payload.EmbeddedId; - FileInfo fileInfo = new FileInfo(payload.SourceFile.Path); - - // Skip adding same file if unmodified - ZipArchiveEntry entry = zipFile.CreateEntry(entryName); - entry.LastWriteTime = fileInfo.LastWriteTime; - using (Stream ws = entry.Open()) - { - using (FileStream rs = File.Open(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) - { - rs.CopyTo(ws); - } - } - } - } - } - catch (Exception ex) - { - Messaging.Write(PanelSwWixErrorMessages.ContainerError(container.SourceLineNumbers, container.Id.Id, ex.Message)); - return; - } - - CalculateHashAndSize(container.WorkingPath, out sha512, out size); - } - } -} diff --git a/nuget.config b/nuget.config new file mode 100644 index 00000000..d288c677 --- /dev/null +++ b/nuget.config @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.editorconfig b/src/.editorconfig similarity index 100% rename from .editorconfig rename to src/.editorconfig diff --git a/src/7Zap b/src/7Zap new file mode 160000 index 00000000..097df004 --- /dev/null +++ b/src/7Zap @@ -0,0 +1 @@ +Subproject commit 097df004b2a306833158326f3dc47fffb8c973ed diff --git a/CaCommon/CaCommon.vcxproj b/src/CaCommon/CaCommon.vcxproj similarity index 98% rename from CaCommon/CaCommon.vcxproj rename to src/CaCommon/CaCommon.vcxproj index 22afb1cc..d5285da6 100644 --- a/CaCommon/CaCommon.vcxproj +++ b/src/CaCommon/CaCommon.vcxproj @@ -1,113 +1,113 @@ - - - - - - Release - Win32 - - - Release - x64 - - - - native,Version=v0.0 - {7C6B230A-9186-4C1E-B61D-E803CC36A347} - CaCommon - CaCommon - Win32Proj - true - StaticLibrary - Unicode - Static - true - .lib - false - - - - - - - - - MinSpace - true - NDEBUG;WIN32;_WINDOWS;_USRDLL;EXAMPLECADLL_EXPORTS;FullVersion="$(FullVersion)";%(PreprocessorDefinitions) - MultiThreaded - true - ProgramDatabase - false - $(IntDir)\..\Protobuf;..\protobuf\src;%(AdditionalIncludeDirectories) - Use - pch.h - Level3 - - - libprotobuf-lite.lib;ProtoCaLib.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;msxml2.lib;User32.lib;%(AdditionalDependencies) - CustomAction.def - true - Windows - MachineX86 - true - true - - - false - $(BuildFolderCommon)$(Platform)\protobuf\$(Configuration);$(OutDir)\..\ProtoCaLib;%(AdditionalLibraryDirectories) - - - - - - - - - - - - Create - - - - - - True - - - True - - - - - - - - - - - - - - - - - - - - - protobuf\command.proto - - - protobuf\customActionData.proto - - - - - - - - - + + + + + + Release + Win32 + + + Release + x64 + + + + native,Version=v0.0 + {7C6B230A-9186-4C1E-B61D-E803CC36A347} + CaCommon + CaCommon + Win32Proj + true + StaticLibrary + Unicode + Static + true + .lib + false + + + + + + + + + MinSpace + true + NDEBUG;WIN32;_WINDOWS;_USRDLL;EXAMPLECADLL_EXPORTS;FullVersion="$(FullVersion)";%(PreprocessorDefinitions) + MultiThreaded + true + ProgramDatabase + false + $(IntDir)\..\Protobuf;..\protobuf\src;%(AdditionalIncludeDirectories) + Use + pch.h + Level3 + + + libprotobuf-lite.lib;ProtoCaLib.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;msxml2.lib;User32.lib;%(AdditionalDependencies) + CustomAction.def + true + Windows + MachineX86 + true + true + + + false + $(BuildFolderCommon)$(Platform)\protobuf\$(Configuration);$(OutDir)\..\ProtoCaLib;%(AdditionalLibraryDirectories) + + + + + + + + + + + + Create + + + + + + True + + + True + + + + + + + + + + + + + + + + + + + + + protobuf\command.proto + + + protobuf\customActionData.proto + + + + + + + + + \ No newline at end of file diff --git a/CaCommon/CaCommon.vcxproj.filters b/src/CaCommon/CaCommon.vcxproj.filters similarity index 97% rename from CaCommon/CaCommon.vcxproj.filters rename to src/CaCommon/CaCommon.vcxproj.filters index ef33955c..d7015f47 100644 --- a/CaCommon/CaCommon.vcxproj.filters +++ b/src/CaCommon/CaCommon.vcxproj.filters @@ -1,106 +1,106 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - {20c1b625-9539-43c6-b9fc-3e7db24be2da} - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Protobuf - - - Protobuf - - - - - Resource Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + {20c1b625-9539-43c6-b9fc-3e7db24be2da} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Protobuf + + + Protobuf + + + + + Resource Files + + \ No newline at end of file diff --git a/CaCommon/DeferredActionBase.cpp b/src/CaCommon/DeferredActionBase.cpp similarity index 95% rename from CaCommon/DeferredActionBase.cpp rename to src/CaCommon/DeferredActionBase.cpp index 186c470e..5aebb57e 100644 --- a/CaCommon/DeferredActionBase.cpp +++ b/src/CaCommon/DeferredActionBase.cpp @@ -1,413 +1,413 @@ -#include "pch.h" -#include "DeferredActionBase.h" -#include "WixString.h" -#include -#include -#include -using namespace ::com::panelsw::ca; - -static void FirstLog(MSIHANDLE hInstall, LPCSTR szMessage); - -HRESULT CDeferredActionBase::DeferredEntryPoint(MSIHANDLE hInstall, ReceiverToExecutorFunc mapFunc) -{ - HRESULT hr = S_OK; - HRESULT hrErr = S_OK; - LPWSTR szCustomActionData = nullptr; - BYTE* pData = nullptr; - SIZE_T nDataSize = 0; - BOOL bRes = TRUE; - CDeferredActionBase* pExecutor = nullptr; - CustomActionData cad; - BOOL bIsRollback = FALSE; - BOOL bIsWow64Initialized = FALSE; - BOOL bRedirected = FALSE; - - // Get CustomActionData - UINT er = ERROR_SUCCESS; - DWORD_PTR cch = 0; - WCHAR szEmpty[1] = L""; - er = ::MsiGetPropertyW(hInstall, L"CustomActionData", szEmpty, (DWORD*)&cch); - if ((er != ERROR_MORE_DATA) && (er != ERROR_SUCCESS)) - { - hr = E_FAIL; - FirstLog(hInstall, "Failed getting CustomActionData"); - ExitFunction(); - } - - hr = StrAlloc(&szCustomActionData, ++cch); - if (FAILED(hr)) - { - FirstLog(hInstall, "Failed getting CustomActionData"); - ExitFunction(); - } - - er = ::MsiGetPropertyW(hInstall, L"CustomActionData", szCustomActionData, (DWORD*)&cch); - if (er != ERROR_SUCCESS) - { - hr = E_FAIL; - FirstLog(hInstall, "Failed getting CustomActionData"); - ExitFunction(); - } - - if (!(szCustomActionData && *szCustomActionData)) - { - FirstLog(hInstall, "Nothing to do"); - ExitFunction(); - } - - hr = StrAllocBase85Decode(szCustomActionData, &pData, &nDataSize); - if (FAILED(hr)) - { - FirstLog(hInstall, "Failed decoding CustomActionData"); - ExitFunction(); - } - - bRes = cad.ParseFromArray(pData, nDataSize); - if (!bRes) - { - hr = E_FAIL; - FirstLog(hInstall, "Failed parsing CustomActionData"); - ExitFunction(); - } - - hr = WcaInitialize(hInstall, cad.id().c_str()); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - bIsWow64Initialized = (WcaInitializeWow64() == S_OK); - if (bIsWow64Initialized) - { - hr = WcaDisableWow64FSRedirection(); - bRedirected = SUCCEEDED(hr); - if (!bRedirected) - { - WcaLogError(hr, "Failed to enable filesystem redirection."); - hr = S_OK; - } - } - - // During rollback we don't exit on failure before completing cleanup. - bIsRollback = ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE::MSIRUNMODE_ROLLBACK); - - // Iterate elements - for (const Command& cmd : cad.commands()) - { - if (cmd.handler().empty()) - { - continue; - } - - // Get receiver - hr = mapFunc(cmd.handler().c_str(), &pExecutor); - if (bIsRollback && FAILED(hr)) - { - WcaLogError(hr, "Failed to get CDeferredActionBase for '%hs'", cmd.handler().c_str()); - hrErr = hr; - hr = S_OK; - goto LContinue; - } - ExitOnFailure(hr, "Failed to get CDeferredActionBase for '%hs'", cmd.handler().c_str()); - - // Execute - hr = pExecutor->DeferredExecute(cmd.details()); - if (bIsRollback && FAILED(hr)) - { - WcaLogError(hr, "Failed"); - hrErr = hr; - hr = S_OK; - goto LContinue; - } - ExitOnFailure(hr, "Failed"); - - hr = WcaProgressMessage(cmd.cost(), FALSE); - if (bIsRollback && FAILED(hr)) - { - WcaLogError(hr, "Failed to report progress by cost"); - hrErr = hr; - hr = S_OK; - goto LContinue; - } - ExitOnFailure(hr, "Failed to report progress by cost"); - - LContinue: - - // Release CDeferredActionBase. - if (pExecutor) - { - delete pExecutor; - pExecutor = nullptr; - } - } - -LExit: - - if (bRedirected) - { - WcaRevertWow64FSRedirection(); - } - if (bIsWow64Initialized) - { - WcaFinalizeWow64(); - } - - ReleaseStr(szCustomActionData); - ReleaseMem(pData); - if (pExecutor) - { - delete pExecutor; - } - - return SUCCEEDED(hr) ? hrErr : hr; -} - -CDeferredActionBase::CDeferredActionBase(LPCSTR szId) -{ - _cad.set_id(szId); -} - -CDeferredActionBase::~CDeferredActionBase() -{ -} - -HRESULT CDeferredActionBase::DoDeferredAction(LPCWSTR szCustomActionName) -{ - HRESULT hr = S_OK; - CWixString szCustomActionData; - - if (_cad.commands_size() > 0) - { - hr = GetCustomActionData((LPWSTR*)szCustomActionData); - ExitOnFailure(hr, "Failed getting custom action data for commit action."); - - hr = WcaDoDeferredAction(szCustomActionName, (LPCWSTR)szCustomActionData, GetCost()); - ExitOnFailure(hr, "Failed scheduling deferred action '%ls'.", szCustomActionName); - } - -LExit: - return hr; -} - -HRESULT CDeferredActionBase::SetCustomActionData(LPCWSTR szPropertyName) -{ - HRESULT hr = S_OK; - CWixString szCustomActionData; - - if (_cad.commands_size() > 0) - { - hr = GetCustomActionData((LPWSTR*)szCustomActionData); - ExitOnFailure(hr, "Failed getting custom action data for commit action."); - - hr = WcaSetProperty(szPropertyName, (LPCWSTR)szCustomActionData); - ExitOnFailure(hr, "Failed setting CustomActionData to property '%ls'.", szPropertyName); - } - -LExit: - return hr; -} - -UINT CDeferredActionBase::GetCost() const -{ - UINT cost = 0; - for each (const Command cmd in _cad.commands()) - { - cost += cmd.cost(); - } - return cost; -} - -HRESULT CDeferredActionBase::AddCommand(LPCSTR szHandler, Command** ppCommand) -{ - HRESULT hr = S_OK; - Command* pCmd = nullptr; - - pCmd = _cad.add_commands(); - - pCmd->set_handler(szHandler); - - *ppCommand = pCmd; - pCmd = nullptr; - - if (pCmd) - { - _cad.mutable_commands()->RemoveLast(); - } - - return hr; -} - -HRESULT CDeferredActionBase::GetCustomActionData(LPWSTR* pszCustomActionData) -{ - HRESULT hr = S_OK; - BOOL bRes = TRUE; - std::string srlz; - LPWSTR szCustomActionData = nullptr; - - bRes = _cad.SerializeToString(&srlz); - ExitOnNull(bRes, hr, E_FAIL, "Failed serializing CustomActionData"); - - hr = StrAllocBase85Encode((const BYTE*)srlz.data(), srlz.size(), &szCustomActionData); - ExitOnFailure(hr, "Failed encode CustomActionData"); - - *pszCustomActionData = szCustomActionData; - szCustomActionData = nullptr; - -LExit: - ReleaseStr(szCustomActionData); - - return hr; -} - -HRESULT CDeferredActionBase::Prepend(CDeferredActionBase* pOther) -{ - HRESULT hr = S_OK; - CustomActionData mergedCad; - mergedCad.set_id(_cad.id()); - - for (const Command& cmd : pOther->_cad.commands()) - { - Command* pNewCmd = mergedCad.add_commands(); - ExitOnNull(pNewCmd, hr, E_FAIL, "Failed to allocate command"); - - pNewCmd->CopyFrom(cmd); - } - - for (const Command& cmd : _cad.commands()) - { - Command* pNewCmd = mergedCad.add_commands(); - ExitOnNull(pNewCmd, hr, E_FAIL, "Failed to allocate command"); - - pNewCmd->CopyFrom(cmd); - } - - _cad.Clear(); - _cad.CopyFrom(mergedCad); - -LExit: - return hr; -} - -void CDeferredActionBase::LogUnformatted(LOGLEVEL level, bool bShowTime, LPCWSTR szFormat, ...) -{ - HRESULT hr = S_OK; - int nRes = 0; - LPWSTR szTime = nullptr; - LPWSTR szFormattedTime = nullptr; - LPWSTR szMessage = nullptr; - LPCSTR szLogName = nullptr; - va_list va = nullptr; - size_t nSize = 0; - PMSIHANDLE hRec; - - nSize = 256; - do - { - nSize *= 2; - if (nSize > STRSAFE_MAX_CCH) // Print a truncated message - { - hr = S_OK; - break; - } - - if (va) - { - va_end(va); - } - - va_start(va, szFormat); - ReleaseNullStr(szMessage); - - hr = StrAlloc(&szMessage, nSize); - ExitOnFailure(hr, "Failed to allocate memory"); - - hr = ::StringCchVPrintfW(szMessage, nSize, szFormat, va); - } while (hr == STRSAFE_E_INSUFFICIENT_BUFFER); - ExitOnFailure(hr, "Failed to format log message"); - - // Replace non-printable characters with spaces - for (LPWSTR szCurr = szMessage; szCurr && *szCurr; ++szCurr) - { - int chr = ((int)szCurr[0]) & 0xFFFF; - if (::iswcntrl(chr) || ::iswspace(chr) || !::iswprint(chr)) - { - szCurr[0] = L' '; - } - } - - if (bShowTime) - { - SYSTEMTIME sysTime; - - ::GetLocalTime(&sysTime); // Grab the time once to ensure both calls to GetTimeFormatW() require the same buffer size - - nRes = ::GetTimeFormatW(LOCALE_INVARIANT, TIME_FORCE24HOURFORMAT, &sysTime, nullptr, nullptr, 0); - if (nRes) - { - if (SUCCEEDED(StrAlloc(&szTime, nRes))) - { - nRes = ::GetTimeFormatW(LOCALE_INVARIANT, TIME_FORCE24HOURFORMAT, &sysTime, nullptr, szTime, nRes); - if (nRes) - { - StrAllocFormatted(&szFormattedTime, L" (%ls)", szTime); - } - } - } - } - - hRec = ::MsiCreateRecord(4); - ExitOnNullWithLastError(hRec, hr, "Failed to create record"); - - szLogName = WcaGetLogName(); - if (szLogName && *szLogName) - { - hr = WcaSetRecordString(hRec, 0, L"[1][2]: [3]"); - ExitOnFailure(hr, "Failed to set log record"); - - nRes = ::MsiRecordSetStringA(hRec, 1, szLogName); - ExitOnWin32Error(nRes, hr, "Failed to set log record"); - - hr = WcaSetRecordString(hRec, 2, szFormattedTime ? szFormattedTime : L""); - ExitOnFailure(hr, "Failed to set log record"); - - hr = WcaSetRecordString(hRec, 3, szMessage); - ExitOnFailure(hr, "Failed to set log record"); - } - else - { - hr = WcaSetRecordString(hRec, 0, L"[1][2]"); - ExitOnFailure(hr, "Failed to set log record"); - - hr = WcaSetRecordString(hRec, 1, szFormattedTime ? szFormattedTime : L""); - ExitOnFailure(hr, "Failed to set log record"); - - hr = WcaSetRecordString(hRec, 2, szMessage); - ExitOnFailure(hr, "Failed to set log record"); - } - - WcaProcessMessage(INSTALLMESSAGE_INFO, hRec); - -LExit: - - ReleaseStr(szTime); - ReleaseStr(szFormattedTime); - ReleaseStr(szMessage); - if (va) - { - va_end(va); - } - return; -} - -static void FirstLog(MSIHANDLE hInstall, LPCSTR szMessage) -{ - HRESULT hr = S_OK; - - if (!WcaIsInitialized()) - { - hr = WcaInitialize(hInstall, "CommonDeferred"); - } - - if (SUCCEEDED(hr)) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, szMessage); - } -} +#include "pch.h" +#include "DeferredActionBase.h" +#include "WixString.h" +#include +#include +#include +using namespace ::com::panelsw::ca; + +static void FirstLog(MSIHANDLE hInstall, LPCSTR szMessage); + +HRESULT CDeferredActionBase::DeferredEntryPoint(MSIHANDLE hInstall, ReceiverToExecutorFunc mapFunc) +{ + HRESULT hr = S_OK; + HRESULT hrErr = S_OK; + LPWSTR szCustomActionData = nullptr; + BYTE* pData = nullptr; + SIZE_T nDataSize = 0; + BOOL bRes = TRUE; + CDeferredActionBase* pExecutor = nullptr; + CustomActionData cad; + BOOL bIsRollback = FALSE; + BOOL bIsWow64Initialized = FALSE; + BOOL bRedirected = FALSE; + + // Get CustomActionData + UINT er = ERROR_SUCCESS; + DWORD_PTR cch = 0; + WCHAR szEmpty[1] = L""; + er = ::MsiGetPropertyW(hInstall, L"CustomActionData", szEmpty, (DWORD*)&cch); + if ((er != ERROR_MORE_DATA) && (er != ERROR_SUCCESS)) + { + hr = E_FAIL; + FirstLog(hInstall, "Failed getting CustomActionData"); + ExitFunction(); + } + + hr = StrAlloc(&szCustomActionData, ++cch); + if (FAILED(hr)) + { + FirstLog(hInstall, "Failed getting CustomActionData"); + ExitFunction(); + } + + er = ::MsiGetPropertyW(hInstall, L"CustomActionData", szCustomActionData, (DWORD*)&cch); + if (er != ERROR_SUCCESS) + { + hr = E_FAIL; + FirstLog(hInstall, "Failed getting CustomActionData"); + ExitFunction(); + } + + if (!(szCustomActionData && *szCustomActionData)) + { + FirstLog(hInstall, "Nothing to do"); + ExitFunction(); + } + + hr = StrAllocBase85Decode(szCustomActionData, &pData, &nDataSize); + if (FAILED(hr)) + { + FirstLog(hInstall, "Failed decoding CustomActionData"); + ExitFunction(); + } + + bRes = cad.ParseFromArray(pData, nDataSize); + if (!bRes) + { + hr = E_FAIL; + FirstLog(hInstall, "Failed parsing CustomActionData"); + ExitFunction(); + } + + hr = WcaInitialize(hInstall, cad.id().c_str()); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + bIsWow64Initialized = (WcaInitializeWow64() == S_OK); + if (bIsWow64Initialized) + { + hr = WcaDisableWow64FSRedirection(); + bRedirected = SUCCEEDED(hr); + if (!bRedirected) + { + WcaLogError(hr, "Failed to enable filesystem redirection."); + hr = S_OK; + } + } + + // During rollback we don't exit on failure before completing cleanup. + bIsRollback = ::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE::MSIRUNMODE_ROLLBACK); + + // Iterate elements + for (const Command& cmd : cad.commands()) + { + if (cmd.handler().empty()) + { + continue; + } + + // Get receiver + hr = mapFunc(cmd.handler().c_str(), &pExecutor); + if (bIsRollback && FAILED(hr)) + { + WcaLogError(hr, "Failed to get CDeferredActionBase for '%hs'", cmd.handler().c_str()); + hrErr = hr; + hr = S_OK; + goto LContinue; + } + ExitOnFailure(hr, "Failed to get CDeferredActionBase for '%hs'", cmd.handler().c_str()); + + // Execute + hr = pExecutor->DeferredExecute(cmd.details()); + if (bIsRollback && FAILED(hr)) + { + WcaLogError(hr, "Failed"); + hrErr = hr; + hr = S_OK; + goto LContinue; + } + ExitOnFailure(hr, "Failed"); + + hr = WcaProgressMessage(cmd.cost(), FALSE); + if (bIsRollback && FAILED(hr)) + { + WcaLogError(hr, "Failed to report progress by cost"); + hrErr = hr; + hr = S_OK; + goto LContinue; + } + ExitOnFailure(hr, "Failed to report progress by cost"); + + LContinue: + + // Release CDeferredActionBase. + if (pExecutor) + { + delete pExecutor; + pExecutor = nullptr; + } + } + +LExit: + + if (bRedirected) + { + WcaRevertWow64FSRedirection(); + } + if (bIsWow64Initialized) + { + WcaFinalizeWow64(); + } + + ReleaseStr(szCustomActionData); + ReleaseMem(pData); + if (pExecutor) + { + delete pExecutor; + } + + return SUCCEEDED(hr) ? hrErr : hr; +} + +CDeferredActionBase::CDeferredActionBase(LPCSTR szId) +{ + _cad.set_id(szId); +} + +CDeferredActionBase::~CDeferredActionBase() +{ +} + +HRESULT CDeferredActionBase::DoDeferredAction(LPCWSTR szCustomActionName) +{ + HRESULT hr = S_OK; + CWixString szCustomActionData; + + if (_cad.commands_size() > 0) + { + hr = GetCustomActionData((LPWSTR*)szCustomActionData); + ExitOnFailure(hr, "Failed getting custom action data for commit action."); + + hr = WcaDoDeferredAction(szCustomActionName, (LPCWSTR)szCustomActionData, GetCost()); + ExitOnFailure(hr, "Failed scheduling deferred action '%ls'.", szCustomActionName); + } + +LExit: + return hr; +} + +HRESULT CDeferredActionBase::SetCustomActionData(LPCWSTR szPropertyName) +{ + HRESULT hr = S_OK; + CWixString szCustomActionData; + + if (_cad.commands_size() > 0) + { + hr = GetCustomActionData((LPWSTR*)szCustomActionData); + ExitOnFailure(hr, "Failed getting custom action data for commit action."); + + hr = WcaSetProperty(szPropertyName, (LPCWSTR)szCustomActionData); + ExitOnFailure(hr, "Failed setting CustomActionData to property '%ls'.", szPropertyName); + } + +LExit: + return hr; +} + +UINT CDeferredActionBase::GetCost() const +{ + UINT cost = 0; + for each (const Command cmd in _cad.commands()) + { + cost += cmd.cost(); + } + return cost; +} + +HRESULT CDeferredActionBase::AddCommand(LPCSTR szHandler, Command** ppCommand) +{ + HRESULT hr = S_OK; + Command* pCmd = nullptr; + + pCmd = _cad.add_commands(); + + pCmd->set_handler(szHandler); + + *ppCommand = pCmd; + pCmd = nullptr; + + if (pCmd) + { + _cad.mutable_commands()->RemoveLast(); + } + + return hr; +} + +HRESULT CDeferredActionBase::GetCustomActionData(LPWSTR* pszCustomActionData) +{ + HRESULT hr = S_OK; + BOOL bRes = TRUE; + std::string srlz; + LPWSTR szCustomActionData = nullptr; + + bRes = _cad.SerializeToString(&srlz); + ExitOnNull(bRes, hr, E_FAIL, "Failed serializing CustomActionData"); + + hr = StrAllocBase85Encode((const BYTE*)srlz.data(), srlz.size(), &szCustomActionData); + ExitOnFailure(hr, "Failed encode CustomActionData"); + + *pszCustomActionData = szCustomActionData; + szCustomActionData = nullptr; + +LExit: + ReleaseStr(szCustomActionData); + + return hr; +} + +HRESULT CDeferredActionBase::Prepend(CDeferredActionBase* pOther) +{ + HRESULT hr = S_OK; + CustomActionData mergedCad; + mergedCad.set_id(_cad.id()); + + for (const Command& cmd : pOther->_cad.commands()) + { + Command* pNewCmd = mergedCad.add_commands(); + ExitOnNull(pNewCmd, hr, E_FAIL, "Failed to allocate command"); + + pNewCmd->CopyFrom(cmd); + } + + for (const Command& cmd : _cad.commands()) + { + Command* pNewCmd = mergedCad.add_commands(); + ExitOnNull(pNewCmd, hr, E_FAIL, "Failed to allocate command"); + + pNewCmd->CopyFrom(cmd); + } + + _cad.Clear(); + _cad.CopyFrom(mergedCad); + +LExit: + return hr; +} + +void CDeferredActionBase::LogUnformatted(LOGLEVEL level, bool bShowTime, LPCWSTR szFormat, ...) +{ + HRESULT hr = S_OK; + int nRes = 0; + LPWSTR szTime = nullptr; + LPWSTR szFormattedTime = nullptr; + LPWSTR szMessage = nullptr; + LPCSTR szLogName = nullptr; + va_list va = nullptr; + size_t nSize = 0; + PMSIHANDLE hRec; + + nSize = 256; + do + { + nSize *= 2; + if (nSize > STRSAFE_MAX_CCH) // Print a truncated message + { + hr = S_OK; + break; + } + + if (va) + { + va_end(va); + } + + va_start(va, szFormat); + ReleaseNullStr(szMessage); + + hr = StrAlloc(&szMessage, nSize); + ExitOnFailure(hr, "Failed to allocate memory"); + + hr = ::StringCchVPrintfW(szMessage, nSize, szFormat, va); + } while (hr == STRSAFE_E_INSUFFICIENT_BUFFER); + ExitOnFailure(hr, "Failed to format log message"); + + // Replace non-printable characters with spaces + for (LPWSTR szCurr = szMessage; szCurr && *szCurr; ++szCurr) + { + int chr = ((int)szCurr[0]) & 0xFFFF; + if (::iswcntrl(chr) || ::iswspace(chr) || !::iswprint(chr)) + { + szCurr[0] = L' '; + } + } + + if (bShowTime) + { + SYSTEMTIME sysTime; + + ::GetLocalTime(&sysTime); // Grab the time once to ensure both calls to GetTimeFormatW() require the same buffer size + + nRes = ::GetTimeFormatW(LOCALE_INVARIANT, TIME_FORCE24HOURFORMAT, &sysTime, nullptr, nullptr, 0); + if (nRes) + { + if (SUCCEEDED(StrAlloc(&szTime, nRes))) + { + nRes = ::GetTimeFormatW(LOCALE_INVARIANT, TIME_FORCE24HOURFORMAT, &sysTime, nullptr, szTime, nRes); + if (nRes) + { + StrAllocFormatted(&szFormattedTime, L" (%ls)", szTime); + } + } + } + } + + hRec = ::MsiCreateRecord(4); + ExitOnNullWithLastError(hRec, hr, "Failed to create record"); + + szLogName = WcaGetLogName(); + if (szLogName && *szLogName) + { + hr = WcaSetRecordString(hRec, 0, L"[1][2]: [3]"); + ExitOnFailure(hr, "Failed to set log record"); + + nRes = ::MsiRecordSetStringA(hRec, 1, szLogName); + ExitOnWin32Error(nRes, hr, "Failed to set log record"); + + hr = WcaSetRecordString(hRec, 2, szFormattedTime ? szFormattedTime : L""); + ExitOnFailure(hr, "Failed to set log record"); + + hr = WcaSetRecordString(hRec, 3, szMessage); + ExitOnFailure(hr, "Failed to set log record"); + } + else + { + hr = WcaSetRecordString(hRec, 0, L"[1][2]"); + ExitOnFailure(hr, "Failed to set log record"); + + hr = WcaSetRecordString(hRec, 1, szFormattedTime ? szFormattedTime : L""); + ExitOnFailure(hr, "Failed to set log record"); + + hr = WcaSetRecordString(hRec, 2, szMessage); + ExitOnFailure(hr, "Failed to set log record"); + } + + WcaProcessMessage(INSTALLMESSAGE_INFO, hRec); + +LExit: + + ReleaseStr(szTime); + ReleaseStr(szFormattedTime); + ReleaseStr(szMessage); + if (va) + { + va_end(va); + } + return; +} + +static void FirstLog(MSIHANDLE hInstall, LPCSTR szMessage) +{ + HRESULT hr = S_OK; + + if (!WcaIsInitialized()) + { + hr = WcaInitialize(hInstall, "CommonDeferred"); + } + + if (SUCCEEDED(hr)) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, szMessage); + } +} diff --git a/CaCommon/DeferredActionBase.h b/src/CaCommon/DeferredActionBase.h similarity index 96% rename from CaCommon/DeferredActionBase.h rename to src/CaCommon/DeferredActionBase.h index df3b60a3..d3369c63 100644 --- a/CaCommon/DeferredActionBase.h +++ b/src/CaCommon/DeferredActionBase.h @@ -1,42 +1,42 @@ -#pragma once -#include "pch.h" -#include -#include "google\protobuf\message_lite.h" -#include "command.pb.h" -#include "customActionData.pb.h" - -#define WSTR_BYTE_SIZE(sz) ((sz) ? (sizeof(WCHAR) * (1 + ::wcslen(sz))) : 0) - -class CDeferredActionBase -{ -public: - CDeferredActionBase(LPCSTR szId); - virtual ~CDeferredActionBase(); - - // Function that maps a receiver name to a CDeferredActionBase inheritor. - typedef HRESULT(*ReceiverToExecutorFunc)(LPCSTR szReceiver, CDeferredActionBase** ppExecutor); - static HRESULT DeferredEntryPoint(MSIHANDLE hInstall, ReceiverToExecutorFunc mapFunc); - - HRESULT DoDeferredAction(LPCWSTR szCustomActionName); - - HRESULT SetCustomActionData(LPCWSTR szPropertyName); - - UINT GetCost() const; - - HRESULT Prepend(CDeferredActionBase* pOther); - - static void LogUnformatted(LOGLEVEL level, bool bShowTime, LPCWSTR szFormat, ...); - -protected: - - // Overriden by inheriting classes. Execute the command object (XML element) - virtual HRESULT DeferredExecute(const ::std::string& command) = 0; - - HRESULT AddCommand(LPCSTR szHandler, ::com::panelsw::ca::Command **ppCommand); - - HRESULT GetCustomActionData(LPWSTR* pszCustomActionData); - -private: - ::com::panelsw::ca::CustomActionData _cad; -}; - +#pragma once +#include "pch.h" +#include +#include "google\protobuf\message_lite.h" +#include "command.pb.h" +#include "customActionData.pb.h" + +#define WSTR_BYTE_SIZE(sz) ((sz) ? (sizeof(WCHAR) * (1 + ::wcslen(sz))) : 0) + +class CDeferredActionBase +{ +public: + CDeferredActionBase(LPCSTR szId); + virtual ~CDeferredActionBase(); + + // Function that maps a receiver name to a CDeferredActionBase inheritor. + typedef HRESULT(*ReceiverToExecutorFunc)(LPCSTR szReceiver, CDeferredActionBase** ppExecutor); + static HRESULT DeferredEntryPoint(MSIHANDLE hInstall, ReceiverToExecutorFunc mapFunc); + + HRESULT DoDeferredAction(LPCWSTR szCustomActionName); + + HRESULT SetCustomActionData(LPCWSTR szPropertyName); + + UINT GetCost() const; + + HRESULT Prepend(CDeferredActionBase* pOther); + + static void LogUnformatted(LOGLEVEL level, bool bShowTime, LPCWSTR szFormat, ...); + +protected: + + // Overriden by inheriting classes. Execute the command object (XML element) + virtual HRESULT DeferredExecute(const ::std::string& command) = 0; + + HRESULT AddCommand(LPCSTR szHandler, ::com::panelsw::ca::Command **ppCommand); + + HRESULT GetCustomActionData(LPWSTR* pszCustomActionData); + +private: + ::com::panelsw::ca::CustomActionData _cad; +}; + diff --git a/CaCommon/DllMain.cpp b/src/CaCommon/DllMain.cpp similarity index 94% rename from CaCommon/DllMain.cpp rename to src/CaCommon/DllMain.cpp index 5de542a3..e9fd42b1 100644 --- a/CaCommon/DllMain.cpp +++ b/src/CaCommon/DllMain.cpp @@ -1,43 +1,43 @@ -#include "pch.h" -#include -#include - -PROC_FILESYSTEMREDIRECTION _gFsRedirect; -extern "C" BOOL WINAPI DllMain(HINSTANCE hInst, ULONG ulReason, LPVOID) -{ - BOOL bWow64 = FALSE; - HANDLE hProc = NULL; - HRESULT hr = S_OK; - - switch (ulReason) - { - case DLL_PROCESS_ATTACH: - WcaGlobalInitialize(hInst); - - _gFsRedirect.fDisabled = FALSE; - hProc = ::GetCurrentProcess(); - hr = ProcWow64(hProc, &bWow64); - if (SUCCEEDED(hr) && bWow64) - { - hr = ProcDisableWowFileSystemRedirection(&_gFsRedirect); - if (FAILED(hr)) - { - _gFsRedirect.fDisabled = FALSE; - } - } - - break; - - case DLL_PROCESS_DETACH: - WcaGlobalFinalize(); - - if (_gFsRedirect.fDisabled) - { - hr = ProcRevertWowFileSystemRedirection(&_gFsRedirect); - } - - break; - } - - return TRUE; -} +#include "pch.h" +#include +#include + +PROC_FILESYSTEMREDIRECTION _gFsRedirect; +extern "C" BOOL WINAPI DllMain(HINSTANCE hInst, ULONG ulReason, LPVOID) +{ + BOOL bWow64 = FALSE; + HANDLE hProc = NULL; + HRESULT hr = S_OK; + + switch (ulReason) + { + case DLL_PROCESS_ATTACH: + WcaGlobalInitialize(hInst); + + _gFsRedirect.fDisabled = FALSE; + hProc = ::GetCurrentProcess(); + hr = ProcWow64(hProc, &bWow64); + if (SUCCEEDED(hr) && bWow64) + { + hr = ProcDisableWowFileSystemRedirection(&_gFsRedirect); + if (FAILED(hr)) + { + _gFsRedirect.fDisabled = FALSE; + } + } + + break; + + case DLL_PROCESS_DETACH: + WcaGlobalFinalize(); + + if (_gFsRedirect.fDisabled) + { + hr = ProcRevertWowFileSystemRedirection(&_gFsRedirect); + } + + break; + } + + return TRUE; +} diff --git a/CaCommon/ErrorPrompter.h b/src/CaCommon/ErrorPrompter.h similarity index 100% rename from CaCommon/ErrorPrompter.h rename to src/CaCommon/ErrorPrompter.h diff --git a/CaCommon/MsiBreak.cpp b/src/CaCommon/MsiBreak.cpp similarity index 93% rename from CaCommon/MsiBreak.cpp rename to src/CaCommon/MsiBreak.cpp index 11b90323..d572fcc7 100644 --- a/CaCommon/MsiBreak.cpp +++ b/src/CaCommon/MsiBreak.cpp @@ -1,44 +1,44 @@ -#include "pch.h" -#include "MsiBreak.h" -#include - -HRESULT MsiDebugBreak() -{ - HRESULT hr = S_OK; - WCHAR szTest[10]; - DWORD dwRes = 0; - - dwRes = ::GetEnvironmentVariable(L"MSI_BREAK", szTest, 10); - if (dwRes > 0) - { - MsiBreak(); - ExitFunction(); - } - - dwRes = ::GetLastError(); - if (dwRes == ERROR_ENVVAR_NOT_FOUND) - { - hr = S_FALSE; - } - else - { - hr = HRESULT_FROM_WIN32(dwRes); - } - -LExit: - return hr; -} - -HRESULT MsiBreak() -{ - HRESULT hr = S_OK; - DWORD dwPrcId = 0; - WCHAR szMsg[MAX_PATH + 100]; - - dwPrcId = ::GetCurrentProcessId(); - ::StringCbPrintf(szMsg, ARRAYSIZE(szMsg), L"MsiBreak process %u", dwPrcId); - - ::MessageBox(nullptr, szMsg, L"MsiBreak", MB_OK); - - return hr; -} +#include "pch.h" +#include "MsiBreak.h" +#include + +HRESULT MsiDebugBreak() +{ + HRESULT hr = S_OK; + WCHAR szTest[10]; + DWORD dwRes = 0; + + dwRes = ::GetEnvironmentVariable(L"MSI_BREAK", szTest, 10); + if (dwRes > 0) + { + MsiBreak(); + ExitFunction(); + } + + dwRes = ::GetLastError(); + if (dwRes == ERROR_ENVVAR_NOT_FOUND) + { + hr = S_FALSE; + } + else + { + hr = HRESULT_FROM_WIN32(dwRes); + } + +LExit: + return hr; +} + +HRESULT MsiBreak() +{ + HRESULT hr = S_OK; + DWORD dwPrcId = 0; + WCHAR szMsg[MAX_PATH + 100]; + + dwPrcId = ::GetCurrentProcessId(); + ::StringCbPrintf(szMsg, ARRAYSIZE(szMsg), L"MsiBreak process %u", dwPrcId); + + ::MessageBox(nullptr, szMsg, L"MsiBreak", MB_OK); + + return hr; +} diff --git a/CaCommon/MsiBreak.h b/src/CaCommon/MsiBreak.h similarity index 93% rename from CaCommon/MsiBreak.h rename to src/CaCommon/MsiBreak.h index 2c1af22a..f8c15d0c 100644 --- a/CaCommon/MsiBreak.h +++ b/src/CaCommon/MsiBreak.h @@ -1,5 +1,5 @@ -#pragma once -#include "pch.h" - -HRESULT MsiDebugBreak(); -HRESULT MsiBreak(); +#pragma once +#include "pch.h" + +HRESULT MsiDebugBreak(); +HRESULT MsiBreak(); diff --git a/CaCommon/RegistryKey.cpp b/src/CaCommon/RegistryKey.cpp similarity index 100% rename from CaCommon/RegistryKey.cpp rename to src/CaCommon/RegistryKey.cpp diff --git a/CaCommon/RegistryKey.h b/src/CaCommon/RegistryKey.h similarity index 100% rename from CaCommon/RegistryKey.h rename to src/CaCommon/RegistryKey.h diff --git a/CaCommon/SqlClientBase.cpp b/src/CaCommon/SqlClientBase.cpp similarity index 100% rename from CaCommon/SqlClientBase.cpp rename to src/CaCommon/SqlClientBase.cpp diff --git a/CaCommon/SqlClientBase.h b/src/CaCommon/SqlClientBase.h similarity index 100% rename from CaCommon/SqlClientBase.h rename to src/CaCommon/SqlClientBase.h diff --git a/CaCommon/SqlConnection.cpp b/src/CaCommon/SqlConnection.cpp similarity index 100% rename from CaCommon/SqlConnection.cpp rename to src/CaCommon/SqlConnection.cpp diff --git a/CaCommon/SqlConnection.h b/src/CaCommon/SqlConnection.h similarity index 100% rename from CaCommon/SqlConnection.h rename to src/CaCommon/SqlConnection.h diff --git a/CaCommon/SqlQuery.cpp b/src/CaCommon/SqlQuery.cpp similarity index 100% rename from CaCommon/SqlQuery.cpp rename to src/CaCommon/SqlQuery.cpp diff --git a/CaCommon/SqlQuery.h b/src/CaCommon/SqlQuery.h similarity index 100% rename from CaCommon/SqlQuery.h rename to src/CaCommon/SqlQuery.h diff --git a/CaCommon/SummaryStream.cpp b/src/CaCommon/SummaryStream.cpp similarity index 96% rename from CaCommon/SummaryStream.cpp rename to src/CaCommon/SummaryStream.cpp index 84c332e1..4faf1b4a 100644 --- a/CaCommon/SummaryStream.cpp +++ b/src/CaCommon/SummaryStream.cpp @@ -1,127 +1,127 @@ -#include "pch.h" -#include "SummaryStream.h" -#include "WixString.h" -#include - -HRESULT CSummaryStream::IsUserContext() -{ - HRESULT hr = S_OK; - INT iWordCount = 0; - - hr = GetSummaryStreamProperty(SummaryStreamProperties::PID_WORDCOUNT, &iWordCount); - ExitOnFailure(hr, "Failed getting word-count property from summary stream"); - - if ((iWordCount & SummaryStreamWordCount::WORD_COUNT_UAC_COMPLIANT) == SummaryStreamWordCount::WORD_COUNT_UAC_COMPLIANT) - { - hr = S_OK; - } - else - { - hr = S_FALSE; - } - -LExit: - return hr; -} - -HRESULT CSummaryStream::IsPackageX64() -{ - HRESULT hr = S_OK; - CWixString szTemplate; - DWORD dwSemiColonIndex = INFINITE; - DWORD dw64Index = INFINITE; - - hr = GetSummaryStreamProperty(SummaryStreamProperties::PID_TEMPLATE, (LPWSTR*)szTemplate); - ExitOnFailure(hr, "Failed getting template property from summary stream"); - - if (szTemplate.IsNullOrEmpty()) - { - hr = S_FALSE; - ExitFunction(); - } - - // See https://docs.microsoft.com/en-us/windows/win32/msi/template-summary - // Template syntax: '[Platform];[lang1[,lang2[,... ]]]' - dw64Index = szTemplate.Find(L"64"); - if (dw64Index != INFINITE) - { - dwSemiColonIndex = szTemplate.Find(L';'); - if ((dwSemiColonIndex == INFINITE) || (dw64Index < dwSemiColonIndex)) - { - hr = S_OK; - ExitFunction(); - } - } - hr = S_FALSE; - -LExit: - return hr; -} - -HRESULT CSummaryStream::GetSummaryStreamProperty(SummaryStreamProperties iProperty, LPWSTR* pszValue) -{ - HRESULT hr = S_OK; - DWORD dwRes = ERROR_SUCCESS; - MSIHANDLE hDatabase = NULL; - PMSIHANDLE hSummaryInfo; - UINT uiDataType = 0; - DWORD dwDataSize = 0; - FILETIME ftJunk; - INT iJunk; - CWixString szValue; - - ExitOnNull(pszValue, hr, E_INVALIDARG, "pszValue is NULL"); - - hDatabase = WcaGetDatabaseHandle(); - ExitOnNull(hDatabase, hr, E_FAIL, "Failed to get MSI database"); - - dwRes = ::MsiGetSummaryInformation(hDatabase, nullptr, 0, &hSummaryInfo); - ExitOnWin32Error(dwRes, hr, "Failed to open summary stream"); - - dwRes = ::MsiSummaryInfoGetProperty(hSummaryInfo, iProperty, &uiDataType, &iJunk, &ftJunk, L"", &dwDataSize); - if (dwRes != ERROR_MORE_DATA) - { - ExitOnWin32Error(dwRes, hr, "Failed to get summary stream property"); - ExitFunction(); // The property is empty - } - ExitOnNull((uiDataType == VT_LPSTR), hr, E_INVALIDARG, "Property data type is %u. Expected VT_LPSTR", uiDataType); - - ++dwDataSize; - hr = szValue.Allocate(dwDataSize); - ExitOnFailure(hr, "Failed to allocate memory"); - - dwRes = ::MsiSummaryInfoGetProperty(hSummaryInfo, iProperty, &uiDataType, &iJunk, &ftJunk, (LPWSTR)szValue, &dwDataSize); - ExitOnWin32Error(dwRes, hr, "Failed to get summary stream property"); - - *pszValue = szValue; - szValue = nullptr; - -LExit: - return hr; -} - -HRESULT CSummaryStream::GetSummaryStreamProperty(SummaryStreamProperties iProperty, INT* piValue) -{ - HRESULT hr = S_OK; - DWORD dwRes = ERROR_SUCCESS; - MSIHANDLE hDatabase = NULL; - PMSIHANDLE hSummaryInfo; - UINT uiDataType = 0; - DWORD dwDataSize = 0; - FILETIME ftJunk; - - ExitOnNull(piValue, hr, E_INVALIDARG, "pdwValue is NULL"); - - hDatabase = WcaGetDatabaseHandle(); - ExitOnNull(hDatabase, hr, E_FAIL, "Failed to get MSI database"); - - dwRes = ::MsiGetSummaryInformation(hDatabase, nullptr, 0, &hSummaryInfo); - ExitOnWin32Error(dwRes, hr, "Failed to open summary stream"); - - dwRes = ::MsiSummaryInfoGetProperty(hSummaryInfo, iProperty, &uiDataType, piValue, &ftJunk, L"", &dwDataSize); - ExitOnWin32Error(dwRes, hr, "Failed to get summary stream property"); - ExitOnNull(((uiDataType == VT_I4) || (uiDataType == VT_I2)), hr, E_INVALIDARG, "Property data type is %u. Expected VT_I4", uiDataType); - -LExit: - return hr; -} +#include "pch.h" +#include "SummaryStream.h" +#include "WixString.h" +#include + +HRESULT CSummaryStream::IsUserContext() +{ + HRESULT hr = S_OK; + INT iWordCount = 0; + + hr = GetSummaryStreamProperty(SummaryStreamProperties::PID_WORDCOUNT, &iWordCount); + ExitOnFailure(hr, "Failed getting word-count property from summary stream"); + + if ((iWordCount & SummaryStreamWordCount::WORD_COUNT_UAC_COMPLIANT) == SummaryStreamWordCount::WORD_COUNT_UAC_COMPLIANT) + { + hr = S_OK; + } + else + { + hr = S_FALSE; + } + +LExit: + return hr; +} + +HRESULT CSummaryStream::IsPackageX64() +{ + HRESULT hr = S_OK; + CWixString szTemplate; + DWORD dwSemiColonIndex = INFINITE; + DWORD dw64Index = INFINITE; + + hr = GetSummaryStreamProperty(SummaryStreamProperties::PID_TEMPLATE, (LPWSTR*)szTemplate); + ExitOnFailure(hr, "Failed getting template property from summary stream"); + + if (szTemplate.IsNullOrEmpty()) + { + hr = S_FALSE; + ExitFunction(); + } + + // See https://docs.microsoft.com/en-us/windows/win32/msi/template-summary + // Template syntax: '[Platform];[lang1[,lang2[,... ]]]' + dw64Index = szTemplate.Find(L"64"); + if (dw64Index != INFINITE) + { + dwSemiColonIndex = szTemplate.Find(L';'); + if ((dwSemiColonIndex == INFINITE) || (dw64Index < dwSemiColonIndex)) + { + hr = S_OK; + ExitFunction(); + } + } + hr = S_FALSE; + +LExit: + return hr; +} + +HRESULT CSummaryStream::GetSummaryStreamProperty(SummaryStreamProperties iProperty, LPWSTR* pszValue) +{ + HRESULT hr = S_OK; + DWORD dwRes = ERROR_SUCCESS; + MSIHANDLE hDatabase = NULL; + PMSIHANDLE hSummaryInfo; + UINT uiDataType = 0; + DWORD dwDataSize = 0; + FILETIME ftJunk; + INT iJunk; + CWixString szValue; + + ExitOnNull(pszValue, hr, E_INVALIDARG, "pszValue is NULL"); + + hDatabase = WcaGetDatabaseHandle(); + ExitOnNull(hDatabase, hr, E_FAIL, "Failed to get MSI database"); + + dwRes = ::MsiGetSummaryInformation(hDatabase, nullptr, 0, &hSummaryInfo); + ExitOnWin32Error(dwRes, hr, "Failed to open summary stream"); + + dwRes = ::MsiSummaryInfoGetProperty(hSummaryInfo, iProperty, &uiDataType, &iJunk, &ftJunk, L"", &dwDataSize); + if (dwRes != ERROR_MORE_DATA) + { + ExitOnWin32Error(dwRes, hr, "Failed to get summary stream property"); + ExitFunction(); // The property is empty + } + ExitOnNull((uiDataType == VT_LPSTR), hr, E_INVALIDARG, "Property data type is %u. Expected VT_LPSTR", uiDataType); + + ++dwDataSize; + hr = szValue.Allocate(dwDataSize); + ExitOnFailure(hr, "Failed to allocate memory"); + + dwRes = ::MsiSummaryInfoGetProperty(hSummaryInfo, iProperty, &uiDataType, &iJunk, &ftJunk, (LPWSTR)szValue, &dwDataSize); + ExitOnWin32Error(dwRes, hr, "Failed to get summary stream property"); + + *pszValue = szValue; + szValue = nullptr; + +LExit: + return hr; +} + +HRESULT CSummaryStream::GetSummaryStreamProperty(SummaryStreamProperties iProperty, INT* piValue) +{ + HRESULT hr = S_OK; + DWORD dwRes = ERROR_SUCCESS; + MSIHANDLE hDatabase = NULL; + PMSIHANDLE hSummaryInfo; + UINT uiDataType = 0; + DWORD dwDataSize = 0; + FILETIME ftJunk; + + ExitOnNull(piValue, hr, E_INVALIDARG, "pdwValue is NULL"); + + hDatabase = WcaGetDatabaseHandle(); + ExitOnNull(hDatabase, hr, E_FAIL, "Failed to get MSI database"); + + dwRes = ::MsiGetSummaryInformation(hDatabase, nullptr, 0, &hSummaryInfo); + ExitOnWin32Error(dwRes, hr, "Failed to open summary stream"); + + dwRes = ::MsiSummaryInfoGetProperty(hSummaryInfo, iProperty, &uiDataType, piValue, &ftJunk, L"", &dwDataSize); + ExitOnWin32Error(dwRes, hr, "Failed to get summary stream property"); + ExitOnNull(((uiDataType == VT_I4) || (uiDataType == VT_I2)), hr, E_INVALIDARG, "Property data type is %u. Expected VT_I4", uiDataType); + +LExit: + return hr; +} diff --git a/CaCommon/SummaryStream.h b/src/CaCommon/SummaryStream.h similarity index 95% rename from CaCommon/SummaryStream.h rename to src/CaCommon/SummaryStream.h index 1af883cc..5b0ee82d 100644 --- a/CaCommon/SummaryStream.h +++ b/src/CaCommon/SummaryStream.h @@ -1,43 +1,43 @@ -#pragma once -class CSummaryStream -{ -public: - - static HRESULT IsPackageX64(); - static HRESULT IsUserContext(); - -private: - - enum SummaryStreamProperties - { - PID_CODEPAGE = 1, - PID_TITLE = 2, - PID_SUBJECT = 3, - PID_AUTHOR = 4, - PID_KEYWORDS = 5, - PID_COMMENTS = 6, - PID_TEMPLATE = 7, - PID_LASTAUTHOR = 8, - PID_REVNUMBER = 9, - PID_LASTPRINTED = 11, - PID_CREATE_DTM = 12, - PID_LASTSAVE_DTM = 13, - PID_PAGECOUNT = 14, - PID_WORDCOUNT = 15, - PID_CHARCOUNT = 16, - PID_APPNAME = 18, - PID_SECURITY = 19 - }; - - // See https://docs.microsoft.com/en-us/windows/win32/msi/word-count-summary - enum SummaryStreamWordCount - { - WORD_COUNT_SHORT_NAMES = 1, - WORD_COUNT_COMPRESSED = 2, - WORD_COUNT_ADMIN_IMAGE = 4, - WORD_COUNT_UAC_COMPLIANT = 8, - }; - - static HRESULT GetSummaryStreamProperty(SummaryStreamProperties iProperty, LPWSTR* pszValue); - static HRESULT GetSummaryStreamProperty(SummaryStreamProperties iProperty, INT* piValue); +#pragma once +class CSummaryStream +{ +public: + + static HRESULT IsPackageX64(); + static HRESULT IsUserContext(); + +private: + + enum SummaryStreamProperties + { + PID_CODEPAGE = 1, + PID_TITLE = 2, + PID_SUBJECT = 3, + PID_AUTHOR = 4, + PID_KEYWORDS = 5, + PID_COMMENTS = 6, + PID_TEMPLATE = 7, + PID_LASTAUTHOR = 8, + PID_REVNUMBER = 9, + PID_LASTPRINTED = 11, + PID_CREATE_DTM = 12, + PID_LASTSAVE_DTM = 13, + PID_PAGECOUNT = 14, + PID_WORDCOUNT = 15, + PID_CHARCOUNT = 16, + PID_APPNAME = 18, + PID_SECURITY = 19 + }; + + // See https://docs.microsoft.com/en-us/windows/win32/msi/word-count-summary + enum SummaryStreamWordCount + { + WORD_COUNT_SHORT_NAMES = 1, + WORD_COUNT_COMPRESSED = 2, + WORD_COUNT_ADMIN_IMAGE = 4, + WORD_COUNT_UAC_COMPLIANT = 8, + }; + + static HRESULT GetSummaryStreamProperty(SummaryStreamProperties iProperty, LPWSTR* pszValue); + static HRESULT GetSummaryStreamProperty(SummaryStreamProperties iProperty, INT* piValue); }; \ No newline at end of file diff --git a/CaCommon/WixString.h b/src/CaCommon/WixString.h similarity index 94% rename from CaCommon/WixString.h rename to src/CaCommon/WixString.h index 2b5ee63f..ec519ed9 100644 --- a/CaCommon/WixString.h +++ b/src/CaCommon/WixString.h @@ -1,567 +1,567 @@ -#pragma once - -#include "pch.h" -#include -#include -#pragma comment (lib, "Shlwapi.lib") - -class CWixString -{ -public: - CWixString() - { - - } - - CWixString(LPCWSTR pS) - { - Copy(pS); - } - - CWixString(DWORD dwSize) - { - Allocate(dwSize); - } - - ~CWixString() - { - Release(); - } - -#pragma region Copy, move c-tors, assignment operators - - CWixString(const CWixString& other) - { - Copy((LPCWSTR)other); - } - - CWixString(CWixString&& other) - { - _dwCapacity = other._dwCapacity; - _pTokenContext = other._pTokenContext; - _szObfuscated = other._szObfuscated; - _pS = other.Detach(); - } - - CWixString& operator=(CWixString&& other) - { - _dwCapacity = other._dwCapacity; - _pTokenContext = other._pTokenContext; - _szObfuscated = other._szObfuscated; - _pS = other.Detach(); - return *this; - } - - CWixString& operator=(const CWixString& other) - { - Copy(other); - return *this; - } - - CWixString& operator=(LPCWSTR szOther) - { - Copy(szOther); - return *this; - } - - WCHAR& operator[](size_t i) - { - static WCHAR errChr = NULL; - if ((i < 0) || (i >= Capacity())) - { - return errChr; - } - - return _pS[i]; - } - -#pragma endregion - - HRESULT Allocate(DWORD dwSize) - { - HRESULT hr = S_OK; - - Release(); - - hr = StrAlloc(&_pS, dwSize); - ExitOnFailure(hr, "Failed to allocate memory"); - - _dwCapacity = dwSize; - - LExit: - return hr; - } - - HRESULT SecureRelease() - { - if (_pS != nullptr) - { - SecureZeroMemory(_pS, Capacity()); - } - - return Release(); - } - - HRESULT Release() - { - HRESULT hr = S_OK; - - if (_szObfuscated) - { - StrFree(_szObfuscated); - } - - if (_pS) - { - hr = StrFree(_pS); - ExitOnFailure(hr, "Failed to free memory"); - } - - LExit: - _pS = nullptr; - _szObfuscated = nullptr; - _dwCapacity = 0; - _pTokenContext = nullptr; - return hr; - } - - LPWSTR Detach() - { - LPWSTR pS = _pS; - _pS = nullptr; - Release(); - - return pS; - } - - HRESULT Copy(const CWixString &other) - { - HRESULT hr = S_OK; - - Release(); - - hr = Copy(other._pS); - ExitOnFailure(hr, "Failed to copy string"); - - if (other._szObfuscated) - { - hr = StrAllocString(&_szObfuscated, other._szObfuscated, NULL); - ExitOnFailure(hr, "Failed to copy string"); - } - - LExit: - return hr; - } - - HRESULT Copy(LPCWSTR pS, DWORD dwMax = INFINITE) - { - DWORD dwSize = 0; - HRESULT hr = S_OK; - errno_t err = ERROR_SUCCESS; - - Release(); - - if (pS == nullptr) - { - ExitFunction(); - } - - dwSize = ::wcslen(pS); - if (dwMax <= dwSize) - { - dwSize = dwMax; - } - - hr = Allocate(dwSize + 1); - ExitOnFailure(hr, "Failed to allocate memory"); - - // Copying - err = ::wcsncpy_s(_pS, _dwCapacity, pS, dwSize); - ExitOnWin32Error(hr, err, "Failed to copy string"); - - LExit: - return hr; - } - - HRESULT ReplaceAll(LPCWSTR from, LPCWSTR to) - { - HRESULT hr = S_OK; - - ExitOnNull(_pS, hr, E_INVALIDSTATE, "Can't replace in null string"); - - hr = StrReplaceStringAll(&_pS, from, to); - if (FAILED(hr)) - { - Release(); - } - ExitOnFailure(hr, "Failed to replace in string"); - - LExit: - return hr; - } - - HRESULT Substring(DWORD dwStart, DWORD dwLength = INFINITE) - { - HRESULT hr = S_OK; - LPWSTR szOld = nullptr; - - ExitOnNull((dwStart < StrLen()), hr, E_INVALIDSTATE, "Substring start index is out of range"); - - szOld = Detach(); - - hr = Copy(szOld + dwStart, dwLength); - ExitOnFailure(hr, "Failed to copy string"); - - LExit: - ReleaseStr(szOld); - return hr; - } - - HRESULT Format(LPCWSTR stFormat, ...) - { - HRESULT hr = S_OK; - va_list va; - va_start(va, stFormat); - - Release(); - - size_t sSize = ::_vscwprintf(stFormat, va); - if (sSize == 0) - { - ExitFunction(); - } - - ++sSize; - hr = Allocate(sSize); - ExitOnFailure(hr, "Failed allocating memory"); - - vswprintf_s(_pS, Capacity(), stFormat, va); - - LExit: - - va_end(va); - return hr; - } - - LPCWSTR Obfuscated() const - { - return _szObfuscated ? _szObfuscated : _pS; - } - - // Expand MSI-formatted string. - // szFormat: MSI format string - // pszObfuscated: Optional pointer to a string that will contain the obfuscated formatted string - HRESULT MsiFormat(LPCWSTR szFormat, LPWSTR* pszObfuscated = nullptr) - { - HRESULT hr = S_OK; - LPWSTR szNew = nullptr; - LPWSTR szStripped = nullptr; - LPWSTR szObfuscated = nullptr; - LPWSTR szMsiHiddenProperties = nullptr; - LPWSTR szHideMe = nullptr; - - Release(); - - hr = StrAllocString(&szStripped, szFormat, 0); - if (SUCCEEDED(hr)) - { - hr = WcaGetProperty(L"MsiHiddenProperties", &szMsiHiddenProperties); - if (SUCCEEDED(hr) && szMsiHiddenProperties && *szMsiHiddenProperties) - { - for (LPWSTR szContext = nullptr, szProp = ::wcstok_s(szMsiHiddenProperties, L";", &szContext); SUCCEEDED(hr) && szProp; szProp = ::wcstok_s(nullptr, L";", &szContext)) - { - if (szProp && *szProp) - { - hr = StrAllocFormatted(&szHideMe, L"[%ls]", szProp); - if (SUCCEEDED(hr)) - { - hr = StrReplaceStringAll(&szStripped, szHideMe, L"******"); - if (FAILED(hr)) - { - break; - } - - StrFree(szHideMe); - szHideMe = nullptr; - } - } - } - } - - if (SUCCEEDED(hr)) - { - hr = WcaGetFormattedString(szStripped, &szObfuscated); - if (SUCCEEDED(hr)) - { - _szObfuscated = szObfuscated; - szObfuscated = nullptr; - - if (pszObfuscated) - { - StrAllocString(pszObfuscated, _szObfuscated, NULL); - } - } - } - } - - hr = WcaGetFormattedString(szFormat, &szNew); - if (SUCCEEDED(hr)) - { - if (_pS) - { - StrFree(_pS); - } - _pS = szNew; - _dwCapacity = 1 + ::wcslen(szNew); - _pTokenContext = nullptr; - szNew = nullptr; - } - - if (szNew) - { - StrFree(szNew); - } - if (szStripped) - { - StrFree(szStripped); - } - if (szObfuscated) - { - StrFree(szObfuscated); - } - if (szMsiHiddenProperties) - { - StrFree(szMsiHiddenProperties); - } - if (szHideMe) - { - StrFree(szHideMe); - } - - return hr; - } - - HRESULT AppnedFormat(LPCWSTR szFormat, ...) - { - HRESULT hr = S_OK; - va_list va; - LPWSTR szAppend = nullptr; - DWORD dwCapacity = 0; - va_start(va, szFormat); - - hr = StrAllocFormattedArgs(&szAppend, szFormat, va); - ExitOnFailure(hr, "Failed formatting string"); - - hr = StrAllocConcat(&_pS, szAppend, 0); - ExitOnFailure(hr, "Failed appending string"); - - dwCapacity = 1 + ::wcslen(_pS); - if (dwCapacity > _dwCapacity) - { - _dwCapacity = dwCapacity; - } - - if (_szObfuscated) - { - hr = StrAllocConcat(&_szObfuscated, szAppend, 0); - ExitOnFailure(hr, "Failed appending string"); - } - - LExit: - if (FAILED(hr)) - { - Release(); - } - - va_end(va); - ReleaseStr(szAppend); - return hr; - } - - HRESULT ToAnsiString(LPSTR* pszStr) - { - HRESULT hr = StrAnsiAllocFormatted(pszStr, "%ls", _pS); - return hr; - } - -#pragma region Tokenize - - HRESULT Tokenize(LPCWSTR delimiters, LPCWSTR* firstToken) - { - _pTokenContext = nullptr; - (*firstToken) = ::wcstok_s(_pS, delimiters, &_pTokenContext); - - return ((*firstToken) == nullptr) ? E_NOMOREITEMS : S_OK; - } - - HRESULT NextToken(LPCWSTR delimiters, LPCWSTR* nextToken) - { - (*nextToken) = ::wcstok_s(nullptr, delimiters, &_pTokenContext); - - return ((*nextToken) == nullptr) ? E_NOMOREITEMS : S_OK; - } - -#pragma endregion - - DWORD Capacity() const - { - if (_dwCapacity > 0) - { - return _dwCapacity; - } - - if (_pS != nullptr) - { - return (1 + ::wcslen(_pS)); - } - - return 0; - } - - size_t StrLen() const - { - if (_pS != nullptr) - { - return ::wcslen(_pS); - } - - return 0; - } - - operator const WCHAR* () const - { - return _pS; - } - - operator WCHAR* () - { - return _pS; - } - - operator WCHAR** () - { - Release(); - - return &_pS; - } - - BOOL IsNullOrEmpty() const - { - return ((_pS == nullptr) || (*_pS == NULL)); - } - - BOOL operator==(const DWORD_PTR dw) const - { - return (_pS == (WCHAR*)dw); - } - - BOOL Equals(LPCWSTR szOther) - { - if (IsNullOrEmpty()) - { - return FALSE; - } - - return (::wcscmp(_pS, szOther) == 0); - } - - BOOL EqualsIgnoreCase(LPCWSTR szOther) - { - if (IsNullOrEmpty()) - { - return FALSE; - } - - return (::_wcsicmp(_pS, szOther) == 0); - } - - DWORD Count(WCHAR c) const - { - DWORD cnt = 0; - LPCWSTR pos = _pS; - - if (IsNullOrEmpty()) - { - return cnt; - } - - while (pos = ::wcschr(pos, c)) - { - ++cnt; - } - - return cnt; - } - - DWORD Find(LPCWSTR szOther) const - { - LPCWSTR pOther = nullptr; - - if (IsNullOrEmpty()) - { - return INFINITE; - } - - pOther = ::wcsstr(_pS, szOther); - if (pOther == nullptr) - { - return INFINITE; - } - - return (pOther - _pS); - } - - DWORD Find(WCHAR cOther) const - { - LPCWSTR pOther = nullptr; - - if (IsNullOrEmpty()) - { - return INFINITE; - } - - pOther = ::wcschr(_pS, cOther); - if (pOther == nullptr) - { - return INFINITE; - } - - return (pOther - _pS); - } - - DWORD RFind(WCHAR cOther) const - { - LPCWSTR pOther = nullptr; - - if (IsNullOrEmpty()) - { - return INFINITE; - } - - pOther = ::wcsrchr(_pS, cOther); - if (pOther == nullptr) - { - return INFINITE; - } - - return (pOther - _pS); - } - - DWORD FindIgnoreCase(LPCWSTR szOther) const - { - if (IsNullOrEmpty() || !szOther || !*szOther) - { - return INFINITE; - } - - LPCWSTR szOtherFound = ::StrStrIW(_pS, szOther); - return szOtherFound ? (szOtherFound - szOther) : INFINITE; - } - -private: - - LPWSTR _pS = nullptr; - LPWSTR _szObfuscated = nullptr; - LPWSTR _pTokenContext = nullptr; - DWORD _dwCapacity = 0; -}; +#pragma once + +#include "pch.h" +#include +#include +#pragma comment (lib, "Shlwapi.lib") + +class CWixString +{ +public: + CWixString() + { + + } + + CWixString(LPCWSTR pS) + { + Copy(pS); + } + + CWixString(DWORD dwSize) + { + Allocate(dwSize); + } + + ~CWixString() + { + Release(); + } + +#pragma region Copy, move c-tors, assignment operators + + CWixString(const CWixString& other) + { + Copy((LPCWSTR)other); + } + + CWixString(CWixString&& other) + { + _dwCapacity = other._dwCapacity; + _pTokenContext = other._pTokenContext; + _szObfuscated = other._szObfuscated; + _pS = other.Detach(); + } + + CWixString& operator=(CWixString&& other) + { + _dwCapacity = other._dwCapacity; + _pTokenContext = other._pTokenContext; + _szObfuscated = other._szObfuscated; + _pS = other.Detach(); + return *this; + } + + CWixString& operator=(const CWixString& other) + { + Copy(other); + return *this; + } + + CWixString& operator=(LPCWSTR szOther) + { + Copy(szOther); + return *this; + } + + WCHAR& operator[](size_t i) + { + static WCHAR errChr = NULL; + if ((i < 0) || (i >= Capacity())) + { + return errChr; + } + + return _pS[i]; + } + +#pragma endregion + + HRESULT Allocate(DWORD dwSize) + { + HRESULT hr = S_OK; + + Release(); + + hr = StrAlloc(&_pS, dwSize); + ExitOnFailure(hr, "Failed to allocate memory"); + + _dwCapacity = dwSize; + + LExit: + return hr; + } + + HRESULT SecureRelease() + { + if (_pS != nullptr) + { + SecureZeroMemory(_pS, Capacity()); + } + + return Release(); + } + + HRESULT Release() + { + HRESULT hr = S_OK; + + if (_szObfuscated) + { + StrFree(_szObfuscated); + } + + if (_pS) + { + hr = StrFree(_pS); + ExitOnFailure(hr, "Failed to free memory"); + } + + LExit: + _pS = nullptr; + _szObfuscated = nullptr; + _dwCapacity = 0; + _pTokenContext = nullptr; + return hr; + } + + LPWSTR Detach() + { + LPWSTR pS = _pS; + _pS = nullptr; + Release(); + + return pS; + } + + HRESULT Copy(const CWixString &other) + { + HRESULT hr = S_OK; + + Release(); + + hr = Copy(other._pS); + ExitOnFailure(hr, "Failed to copy string"); + + if (other._szObfuscated) + { + hr = StrAllocString(&_szObfuscated, other._szObfuscated, NULL); + ExitOnFailure(hr, "Failed to copy string"); + } + + LExit: + return hr; + } + + HRESULT Copy(LPCWSTR pS, DWORD dwMax = INFINITE) + { + DWORD dwSize = 0; + HRESULT hr = S_OK; + errno_t err = ERROR_SUCCESS; + + Release(); + + if (pS == nullptr) + { + ExitFunction(); + } + + dwSize = ::wcslen(pS); + if (dwMax <= dwSize) + { + dwSize = dwMax; + } + + hr = Allocate(dwSize + 1); + ExitOnFailure(hr, "Failed to allocate memory"); + + // Copying + err = ::wcsncpy_s(_pS, _dwCapacity, pS, dwSize); + ExitOnWin32Error(hr, err, "Failed to copy string"); + + LExit: + return hr; + } + + HRESULT ReplaceAll(LPCWSTR from, LPCWSTR to) + { + HRESULT hr = S_OK; + + ExitOnNull(_pS, hr, E_INVALIDSTATE, "Can't replace in null string"); + + hr = StrReplaceStringAll(&_pS, from, to); + if (FAILED(hr)) + { + Release(); + } + ExitOnFailure(hr, "Failed to replace in string"); + + LExit: + return hr; + } + + HRESULT Substring(DWORD dwStart, DWORD dwLength = INFINITE) + { + HRESULT hr = S_OK; + LPWSTR szOld = nullptr; + + ExitOnNull((dwStart < StrLen()), hr, E_INVALIDSTATE, "Substring start index is out of range"); + + szOld = Detach(); + + hr = Copy(szOld + dwStart, dwLength); + ExitOnFailure(hr, "Failed to copy string"); + + LExit: + ReleaseStr(szOld); + return hr; + } + + HRESULT Format(LPCWSTR stFormat, ...) + { + HRESULT hr = S_OK; + va_list va; + va_start(va, stFormat); + + Release(); + + size_t sSize = ::_vscwprintf(stFormat, va); + if (sSize == 0) + { + ExitFunction(); + } + + ++sSize; + hr = Allocate(sSize); + ExitOnFailure(hr, "Failed allocating memory"); + + vswprintf_s(_pS, Capacity(), stFormat, va); + + LExit: + + va_end(va); + return hr; + } + + LPCWSTR Obfuscated() const + { + return _szObfuscated ? _szObfuscated : _pS; + } + + // Expand MSI-formatted string. + // szFormat: MSI format string + // pszObfuscated: Optional pointer to a string that will contain the obfuscated formatted string + HRESULT MsiFormat(LPCWSTR szFormat, LPWSTR* pszObfuscated = nullptr) + { + HRESULT hr = S_OK; + LPWSTR szNew = nullptr; + LPWSTR szStripped = nullptr; + LPWSTR szObfuscated = nullptr; + LPWSTR szMsiHiddenProperties = nullptr; + LPWSTR szHideMe = nullptr; + + Release(); + + hr = StrAllocString(&szStripped, szFormat, 0); + if (SUCCEEDED(hr)) + { + hr = WcaGetProperty(L"MsiHiddenProperties", &szMsiHiddenProperties); + if (SUCCEEDED(hr) && szMsiHiddenProperties && *szMsiHiddenProperties) + { + for (LPWSTR szContext = nullptr, szProp = ::wcstok_s(szMsiHiddenProperties, L";", &szContext); SUCCEEDED(hr) && szProp; szProp = ::wcstok_s(nullptr, L";", &szContext)) + { + if (szProp && *szProp) + { + hr = StrAllocFormatted(&szHideMe, L"[%ls]", szProp); + if (SUCCEEDED(hr)) + { + hr = StrReplaceStringAll(&szStripped, szHideMe, L"******"); + if (FAILED(hr)) + { + break; + } + + StrFree(szHideMe); + szHideMe = nullptr; + } + } + } + } + + if (SUCCEEDED(hr)) + { + hr = WcaGetFormattedString(szStripped, &szObfuscated); + if (SUCCEEDED(hr)) + { + _szObfuscated = szObfuscated; + szObfuscated = nullptr; + + if (pszObfuscated) + { + StrAllocString(pszObfuscated, _szObfuscated, NULL); + } + } + } + } + + hr = WcaGetFormattedString(szFormat, &szNew); + if (SUCCEEDED(hr)) + { + if (_pS) + { + StrFree(_pS); + } + _pS = szNew; + _dwCapacity = 1 + ::wcslen(szNew); + _pTokenContext = nullptr; + szNew = nullptr; + } + + if (szNew) + { + StrFree(szNew); + } + if (szStripped) + { + StrFree(szStripped); + } + if (szObfuscated) + { + StrFree(szObfuscated); + } + if (szMsiHiddenProperties) + { + StrFree(szMsiHiddenProperties); + } + if (szHideMe) + { + StrFree(szHideMe); + } + + return hr; + } + + HRESULT AppnedFormat(LPCWSTR szFormat, ...) + { + HRESULT hr = S_OK; + va_list va; + LPWSTR szAppend = nullptr; + DWORD dwCapacity = 0; + va_start(va, szFormat); + + hr = StrAllocFormattedArgs(&szAppend, szFormat, va); + ExitOnFailure(hr, "Failed formatting string"); + + hr = StrAllocConcat(&_pS, szAppend, 0); + ExitOnFailure(hr, "Failed appending string"); + + dwCapacity = 1 + ::wcslen(_pS); + if (dwCapacity > _dwCapacity) + { + _dwCapacity = dwCapacity; + } + + if (_szObfuscated) + { + hr = StrAllocConcat(&_szObfuscated, szAppend, 0); + ExitOnFailure(hr, "Failed appending string"); + } + + LExit: + if (FAILED(hr)) + { + Release(); + } + + va_end(va); + ReleaseStr(szAppend); + return hr; + } + + HRESULT ToAnsiString(LPSTR* pszStr) + { + HRESULT hr = StrAnsiAllocFormatted(pszStr, "%ls", _pS); + return hr; + } + +#pragma region Tokenize + + HRESULT Tokenize(LPCWSTR delimiters, LPCWSTR* firstToken) + { + _pTokenContext = nullptr; + (*firstToken) = ::wcstok_s(_pS, delimiters, &_pTokenContext); + + return ((*firstToken) == nullptr) ? E_NOMOREITEMS : S_OK; + } + + HRESULT NextToken(LPCWSTR delimiters, LPCWSTR* nextToken) + { + (*nextToken) = ::wcstok_s(nullptr, delimiters, &_pTokenContext); + + return ((*nextToken) == nullptr) ? E_NOMOREITEMS : S_OK; + } + +#pragma endregion + + DWORD Capacity() const + { + if (_dwCapacity > 0) + { + return _dwCapacity; + } + + if (_pS != nullptr) + { + return (1 + ::wcslen(_pS)); + } + + return 0; + } + + size_t StrLen() const + { + if (_pS != nullptr) + { + return ::wcslen(_pS); + } + + return 0; + } + + operator const WCHAR* () const + { + return _pS; + } + + operator WCHAR* () + { + return _pS; + } + + operator WCHAR** () + { + Release(); + + return &_pS; + } + + BOOL IsNullOrEmpty() const + { + return ((_pS == nullptr) || (*_pS == NULL)); + } + + BOOL operator==(const DWORD_PTR dw) const + { + return (_pS == (WCHAR*)dw); + } + + BOOL Equals(LPCWSTR szOther) + { + if (IsNullOrEmpty()) + { + return FALSE; + } + + return (::wcscmp(_pS, szOther) == 0); + } + + BOOL EqualsIgnoreCase(LPCWSTR szOther) + { + if (IsNullOrEmpty()) + { + return FALSE; + } + + return (::_wcsicmp(_pS, szOther) == 0); + } + + DWORD Count(WCHAR c) const + { + DWORD cnt = 0; + LPCWSTR pos = _pS; + + if (IsNullOrEmpty()) + { + return cnt; + } + + while (pos = ::wcschr(pos, c)) + { + ++cnt; + } + + return cnt; + } + + DWORD Find(LPCWSTR szOther) const + { + LPCWSTR pOther = nullptr; + + if (IsNullOrEmpty()) + { + return INFINITE; + } + + pOther = ::wcsstr(_pS, szOther); + if (pOther == nullptr) + { + return INFINITE; + } + + return (pOther - _pS); + } + + DWORD Find(WCHAR cOther) const + { + LPCWSTR pOther = nullptr; + + if (IsNullOrEmpty()) + { + return INFINITE; + } + + pOther = ::wcschr(_pS, cOther); + if (pOther == nullptr) + { + return INFINITE; + } + + return (pOther - _pS); + } + + DWORD RFind(WCHAR cOther) const + { + LPCWSTR pOther = nullptr; + + if (IsNullOrEmpty()) + { + return INFINITE; + } + + pOther = ::wcsrchr(_pS, cOther); + if (pOther == nullptr) + { + return INFINITE; + } + + return (pOther - _pS); + } + + DWORD FindIgnoreCase(LPCWSTR szOther) const + { + if (IsNullOrEmpty() || !szOther || !*szOther) + { + return INFINITE; + } + + LPCWSTR szOtherFound = ::StrStrIW(_pS, szOther); + return szOtherFound ? (szOtherFound - szOther) : INFINITE; + } + +private: + + LPWSTR _pS = nullptr; + LPWSTR _szObfuscated = nullptr; + LPWSTR _pTokenContext = nullptr; + DWORD _dwCapacity = 0; +}; diff --git a/CaCommon/framework.h b/src/CaCommon/framework.h similarity index 100% rename from CaCommon/framework.h rename to src/CaCommon/framework.h diff --git a/CaCommon/pch.cpp b/src/CaCommon/pch.cpp similarity index 100% rename from CaCommon/pch.cpp rename to src/CaCommon/pch.cpp diff --git a/CaCommon/pch.h b/src/CaCommon/pch.h similarity index 100% rename from CaCommon/pch.h rename to src/CaCommon/pch.h diff --git a/DeferredExePackage/DeferredExePackage.cpp b/src/DeferredExePackage/DeferredExePackage.cpp similarity index 100% rename from DeferredExePackage/DeferredExePackage.cpp rename to src/DeferredExePackage/DeferredExePackage.cpp diff --git a/DeferredExePackage/DeferredExePackage.vcxproj b/src/DeferredExePackage/DeferredExePackage.vcxproj similarity index 100% rename from DeferredExePackage/DeferredExePackage.vcxproj rename to src/DeferredExePackage/DeferredExePackage.vcxproj diff --git a/DeferredExePackage/DeferredExePackage.vcxproj.filters b/src/DeferredExePackage/DeferredExePackage.vcxproj.filters similarity index 100% rename from DeferredExePackage/DeferredExePackage.vcxproj.filters rename to src/DeferredExePackage/DeferredExePackage.vcxproj.filters diff --git a/Directory.Build.props b/src/Directory.Build.props similarity index 94% rename from Directory.Build.props rename to src/Directory.Build.props index e10f2ea6..2e6ad460 100644 --- a/Directory.Build.props +++ b/src/Directory.Build.props @@ -2,7 +2,7 @@ Release - $(MSBuildThisFileDirectory)build\ + $(MSBuildThisFileDirectory)..\build\ $(BaseBuildFolder)obj\$(MSBuildProjectName)\ $(BaseIntermediateOutputPath) PackageReference diff --git a/Directory.Packages.props b/src/Directory.Packages.props similarity index 98% rename from Directory.Packages.props rename to src/Directory.Packages.props index 69062fd7..fae65474 100644 --- a/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -2,7 +2,7 @@ true 4.0.3 - 5.0.0-psw-wix.0246-34 + 5.0.0-psw-wix.0248-35 diff --git a/Dism/Dism.cpp b/src/Dism/Dism.cpp similarity index 100% rename from Dism/Dism.cpp rename to src/Dism/Dism.cpp diff --git a/Dism/Dism.def b/src/Dism/Dism.def similarity index 100% rename from Dism/Dism.def rename to src/Dism/Dism.def diff --git a/Dism/Dism.vcxproj b/src/Dism/Dism.vcxproj similarity index 98% rename from Dism/Dism.vcxproj rename to src/Dism/Dism.vcxproj index 594286ab..92d8dd9e 100644 --- a/Dism/Dism.vcxproj +++ b/src/Dism/Dism.vcxproj @@ -1,100 +1,100 @@ - - - - - - Release - x64 - - - Release - Win32 - - - - native,Version=v0.0 - Win32Proj - {e08bd5f2-b8de-4eee-a77f-fd82678664ac} - Dism - Dism - DynamicLibrary - Unicode - true - false - - - - - - - - - - - - Level3 - true - true - true - WIN32;NDEBUG;EXAMPLECADLL_EXPORTS;_WINDOWS;_USRDLL;FullVersion="$(FullVersion)";%(PreprocessorDefinitions) - true - Use - pch.h - $(DismApiDir)Include;$(WindowsKitSharedDir);$(BuildFolderWin32)obj\$(Configuration)\Protobuf;..\protobuf\src;%(AdditionalIncludeDirectories) - MultiThreaded - - - legacy_stdio_definitions.lib;msi.lib;version.lib;%(AdditionalDependencies) - Windows - true - true - true - false - Dism.def - $(DismApiDir)Lib\amd64;%(AdditionalLibraryDirectories) - - - - - Level3 - true - EXAMPLECADLL_EXPORTS;_WINDOWS;_USRDLL;FullVersion="$(FullVersion)";%(PreprocessorDefinitions) - true - Use - pch.h - MultiThreaded - $(DismApiDir)Include;$(WindowsKitSharedDir);$(BuildFolderWin32)obj\$(Configuration)\Protobuf;..\protobuf\src;%(AdditionalIncludeDirectories) - - - legacy_stdio_definitions.lib;msi.lib;version.lib;%(AdditionalDependencies) - Windows - true - false - Dism.def - $(DismApiDir)Lib\x86;%(AdditionalLibraryDirectories) - - - - - - - - - - - Create - - - - - - - - - - - - - - - + + + + + + Release + x64 + + + Release + Win32 + + + + native,Version=v0.0 + Win32Proj + {e08bd5f2-b8de-4eee-a77f-fd82678664ac} + Dism + Dism + DynamicLibrary + Unicode + true + false + + + + + + + + + + + + Level3 + true + true + true + WIN32;NDEBUG;EXAMPLECADLL_EXPORTS;_WINDOWS;_USRDLL;FullVersion="$(FullVersion)";%(PreprocessorDefinitions) + true + Use + pch.h + $(DismApiDir)Include;$(WindowsKitSharedDir);$(BuildFolderWin32)obj\$(Configuration)\Protobuf;..\protobuf\src;%(AdditionalIncludeDirectories) + MultiThreaded + + + legacy_stdio_definitions.lib;msi.lib;version.lib;%(AdditionalDependencies) + Windows + true + true + true + false + Dism.def + $(DismApiDir)Lib\amd64;%(AdditionalLibraryDirectories) + + + + + Level3 + true + EXAMPLECADLL_EXPORTS;_WINDOWS;_USRDLL;FullVersion="$(FullVersion)";%(PreprocessorDefinitions) + true + Use + pch.h + MultiThreaded + $(DismApiDir)Include;$(WindowsKitSharedDir);$(BuildFolderWin32)obj\$(Configuration)\Protobuf;..\protobuf\src;%(AdditionalIncludeDirectories) + + + legacy_stdio_definitions.lib;msi.lib;version.lib;%(AdditionalDependencies) + Windows + true + false + Dism.def + $(DismApiDir)Lib\x86;%(AdditionalLibraryDirectories) + + + + + + + + + + + Create + + + + + + + + + + + + + + + diff --git a/Dism/Dism.vcxproj.filters b/src/Dism/Dism.vcxproj.filters similarity index 100% rename from Dism/Dism.vcxproj.filters rename to src/Dism/Dism.vcxproj.filters diff --git a/Dism/DllMain.cpp b/src/Dism/DllMain.cpp similarity index 100% rename from Dism/DllMain.cpp rename to src/Dism/DllMain.cpp diff --git a/Dism/framework.h b/src/Dism/framework.h similarity index 100% rename from Dism/framework.h rename to src/Dism/framework.h diff --git a/Dism/pch.cpp b/src/Dism/pch.cpp similarity index 100% rename from Dism/pch.cpp rename to src/Dism/pch.cpp diff --git a/Dism/pch.h b/src/Dism/pch.h similarity index 100% rename from Dism/pch.h rename to src/Dism/pch.h diff --git a/LICENSE.md b/src/LICENSE.md similarity index 100% rename from LICENSE.md rename to src/LICENSE.md diff --git a/Nuget/PanelSwWixExtension4.props b/src/Nuget/PanelSwWixExtension4.props similarity index 100% rename from Nuget/PanelSwWixExtension4.props rename to src/Nuget/PanelSwWixExtension4.props diff --git a/Nuget/PanelSwWixExtension4.targets b/src/Nuget/PanelSwWixExtension4.targets similarity index 100% rename from Nuget/PanelSwWixExtension4.targets rename to src/Nuget/PanelSwWixExtension4.targets diff --git a/src/PanelSwBackendExtension/DllMain.cpp b/src/PanelSwBackendExtension/DllMain.cpp new file mode 100644 index 00000000..265d5a9c --- /dev/null +++ b/src/PanelSwBackendExtension/DllMain.cpp @@ -0,0 +1,20 @@ +#include "pch.h" + +HINSTANCE g_hInstance = NULL; + +extern "C" BOOL WINAPI DllMain(HINSTANCE hInst, ULONG ulReason, LPVOID) +{ + HRESULT hr = S_OK; + + switch (ulReason) + { + case DLL_PROCESS_ATTACH: + g_hInstance = hInst; + break; + case DLL_PROCESS_DETACH: + g_hInstance = NULL; + break; + } + + return TRUE; +} diff --git a/src/PanelSwBackendExtension/IPanelSwContainer.h b/src/PanelSwBackendExtension/IPanelSwContainer.h new file mode 100644 index 00000000..f70e83b9 --- /dev/null +++ b/src/PanelSwBackendExtension/IPanelSwContainer.h @@ -0,0 +1,19 @@ +#pragma once + +#include "pch.h" + +class IPanelSwContainer +{ +public: + virtual HRESULT ContainerOpen(LPCWSTR wzContainerId, LPCWSTR wzFilePath) = 0; + + virtual HRESULT ContainerNextStream(BSTR* psczStreamName) = 0; + + virtual HRESULT ContainerStreamToFile(LPCWSTR wzFileName) = 0; + + virtual HRESULT ContainerStreamToBuffer(BYTE** ppbBuffer, SIZE_T* pcbBuffer) = 0; + + virtual HRESULT ContainerSkipStream() = 0; + + virtual HRESULT ContainerClose() = 0; +}; diff --git a/src/PanelSwBackendExtension/PanelSwBackendExtension.cpp b/src/PanelSwBackendExtension/PanelSwBackendExtension.cpp new file mode 100644 index 00000000..2e5aaf4f --- /dev/null +++ b/src/PanelSwBackendExtension/PanelSwBackendExtension.cpp @@ -0,0 +1,233 @@ +#include "pch.h" +#include "PanelSwBackendExtension.h" +#include "PanelSwZipContainer.h" +#include "PanelSwLzmaContainer.h" +#include +using namespace std; + +CPanelSwBundleExtension::CPanelSwBundleExtension(IBundleExtensionEngine* pEngine) + : CBextBaseBundleExtension(pEngine) +{ + XmlInitialize(); +} + +CPanelSwBundleExtension::~CPanelSwBundleExtension() +{ + Reset(); + XmlUninitialize(); +} + +HRESULT CPanelSwBundleExtension::Reset() +{ + ContainerIterator endIt = _containers.end(); + for (ContainerIterator it = _containers.begin(); it != endIt; ++it) + { + if (*it) + { + delete* it; + } + } + _containers.clear(); + return S_OK; +} + +STDMETHODIMP CPanelSwBundleExtension::ContainerOpen(LPCWSTR wzContainerId, LPCWSTR wzFilePath, LPVOID* pContext) +{ + HRESULT hr = S_OK; + CComPtr pixdManifest; + CComPtr pixnBundleExtension; + CComPtr pixnCompression; + CComVariant compression; + LPWSTR szXPath = nullptr; + IPanelSwContainer* pContainer = nullptr; + + hr = XmlLoadDocumentFromFile(m_sczBundleExtensionDataPath, &pixdManifest); + BextExitOnFailure(hr, "Failed to load bundle extension manifest from path: %ls", m_sczBundleExtensionDataPath); + + hr = BextGetBundleExtensionDataNode(pixdManifest, PANELSW_BACKEND_EXTENSION_ID, &pixnBundleExtension); + BextExitOnFailure(hr, "Failed to get BundleExtension '%ls'", PANELSW_BACKEND_EXTENSION_ID); + + hr = StrAllocFormatted(&szXPath, L"PSW_ContainerExtensionData[@ContainerId='%ls']/@Compression", wzContainerId); + BextExitOnFailure(hr, "Failed to allocate XPath string"); + + hr = XmlSelectSingleNode(pixnBundleExtension, szXPath, &pixnCompression); + BextExitOnFailure(hr, "Failed to get container extension data"); + + hr = pixnCompression->get_nodeValue(&compression); + BextExitOnFailure(hr, "Failed to get container compression"); + + if (::wcsicmp(compression.bstrVal, L"Zip") == 0) + { + pContainer = new CPanelSwZipContainer(); + BextExitOnNull(pContainer, hr, E_FAIL, "Failed to get allocate zip container"); + } + else if (::wcsicmp(compression.bstrVal, L"SevenZip") == 0) + { + pContainer = new CPanelSwLzmaContainer(); + BextExitOnNull(pContainer, hr, E_FAIL, "Failed to get allocate 7z container"); + } + else + { + hr = E_INVALIDDATA; + BextExitOnFailure(hr, "Unsupported container compression '%ls'", compression.bstrVal); + } + + hr = pContainer->ContainerOpen(wzContainerId, wzFilePath); + BextExitOnFailure(hr, "Failed to open container"); + + _containers.push_back(pContainer); + *pContext = pContainer; + pContainer = nullptr; + +LExit: + ReleaseStr(szXPath); + if (pContainer) + { + delete pContainer; + } + + return hr; +} + +STDMETHODIMP CPanelSwBundleExtension::ContainerNextStream(LPVOID pContext, BSTR* psczStreamName) +{ + HRESULT hr = S_OK; + IPanelSwContainer* pContainer = nullptr; + + hr = GetContainer(pContext, &pContainer); + BextExitOnFailure(hr, "Failed to get container"); + + hr = pContainer->ContainerNextStream(psczStreamName); + +LExit: + return hr; +} + +STDMETHODIMP CPanelSwBundleExtension::ContainerStreamToFile(LPVOID pContext, LPCWSTR wzFileName) +{ + HRESULT hr = S_OK; + IPanelSwContainer* pContainer = nullptr; + + hr = GetContainer(pContext, &pContainer); + BextExitOnFailure(hr, "Failed to get container"); + + hr = pContainer->ContainerStreamToFile(wzFileName); + +LExit: + return hr; +} + +STDMETHODIMP CPanelSwBundleExtension::ContainerStreamToBuffer(LPVOID pContext, BYTE** ppbBuffer, SIZE_T* pcbBuffer) +{ + HRESULT hr = S_OK; + IPanelSwContainer* pContainer = nullptr; + + hr = GetContainer(pContext, &pContainer); + BextExitOnFailure(hr, "Failed to get container"); + + hr = pContainer->ContainerStreamToBuffer(ppbBuffer, pcbBuffer); + +LExit: + return hr; +} + +STDMETHODIMP CPanelSwBundleExtension::ContainerSkipStream(LPVOID pContext) +{ + HRESULT hr = S_OK; + IPanelSwContainer* pContainer = nullptr; + + hr = GetContainer(pContext, &pContainer); + BextExitOnFailure(hr, "Failed to get container"); + + hr = pContainer->ContainerSkipStream(); + +LExit: + return hr; +} + +STDMETHODIMP CPanelSwBundleExtension::ContainerClose(LPVOID pContext) +{ + HRESULT hr = S_OK; + IPanelSwContainer* pContainer = nullptr; + + hr = GetContainer(pContext, &pContainer); + BextExitOnFailure(hr, "Failed to get container"); + + hr = pContainer->ContainerClose(); + BextExitOnFailure(hr, "Failed to close container"); + + ReleaseContainer(pContainer); + +LExit: + return hr; +} + +HRESULT CPanelSwBundleExtension::GetContainer(LPVOID pContext, IPanelSwContainer** ppContainer) +{ + HRESULT hr = E_NOTFOUND; + + ContainerIterator endIt = _containers.end(); + for (ContainerIterator it = _containers.begin(); it != endIt; ++it) + { + if (*it == (IPanelSwContainer*)pContext) + { + hr = S_OK; + *ppContainer = (IPanelSwContainer*)pContext; + break; + } + } + + return hr; +} + +HRESULT CPanelSwBundleExtension::ReleaseContainer(IPanelSwContainer* pContainer) +{ + HRESULT hr = E_NOTFOUND; + + ContainerIterator endIt = _containers.end(); + for (ContainerIterator it = _containers.begin(); it != endIt; ++it) + { + if (*it == pContainer) + { + hr = S_OK; + _containers.remove(pContainer); + delete pContainer; + break; + } + } + +LExit: + return hr; +} + +extern "C" HRESULT WINAPI BundleExtensionCreate( + __in const BUNDLE_EXTENSION_CREATE_ARGS * pArgs, + __inout BUNDLE_EXTENSION_CREATE_RESULTS * pResults +) +{ + HRESULT hr = S_OK; + IBundleExtensionEngine* pEngine = nullptr; + CPanelSwBundleExtension* pExtension = nullptr; + + hr = BextInitializeFromCreateArgs(pArgs, &pEngine); + ExitOnFailure(hr, "Failed to initialize bext"); + + pExtension = new CPanelSwBundleExtension(pEngine); + BextExitOnNull(pExtension, hr, E_OUTOFMEMORY, "Failed to create new CPanelSwBundleExtension."); + + hr = pExtension->Initialize(pArgs); + BextExitOnFailure(hr, "CPanelSwBundleExtension initialization failed."); + + pResults->pfnBundleExtensionProc = BextBaseBundleExtensionProc; + pResults->pvBundleExtensionProcContext = pExtension; + +LExit: + ReleaseObject(pEngine); + + return hr; +} + +extern "C" void WINAPI BundleExtensionDestroy() +{ + BextUninitialize(); +} diff --git a/PanelSwBackendExtension/PanelSwBackendExtension.def b/src/PanelSwBackendExtension/PanelSwBackendExtension.def similarity index 100% rename from PanelSwBackendExtension/PanelSwBackendExtension.def rename to src/PanelSwBackendExtension/PanelSwBackendExtension.def diff --git a/PanelSwBackendExtension/PanelSwBackendExtension.h b/src/PanelSwBackendExtension/PanelSwBackendExtension.h similarity index 72% rename from PanelSwBackendExtension/PanelSwBackendExtension.h rename to src/PanelSwBackendExtension/PanelSwBackendExtension.h index 5a6629f6..b8084c9f 100644 --- a/PanelSwBackendExtension/PanelSwBackendExtension.h +++ b/src/PanelSwBackendExtension/PanelSwBackendExtension.h @@ -1,9 +1,7 @@ #pragma once -#include -#include "..\poco\Zip\include\Poco\Zip\ZipArchive.h" -#include -#include +#include "pch.h" +#include class CPanelSwBundleExtension : public CBextBaseBundleExtension { @@ -27,9 +25,10 @@ class CPanelSwBundleExtension : public CBextBaseBundleExtension private: + HRESULT GetContainer(LPVOID pContext, IPanelSwContainer** ppContainer); + HRESULT ReleaseContainer(IPanelSwContainer* pContainer); HRESULT Reset(); - std::auto_ptr _zipStream; - std::auto_ptr _pArchive; - std::string _currFile; + std::list _containers; + typedef std::list::iterator ContainerIterator; }; diff --git a/PanelSwBackendExtension/PanelSwBackendExtension.vcxproj b/src/PanelSwBackendExtension/PanelSwBackendExtension.vcxproj similarity index 62% rename from PanelSwBackendExtension/PanelSwBackendExtension.vcxproj rename to src/PanelSwBackendExtension/PanelSwBackendExtension.vcxproj index b59fde45..a4e662ab 100644 --- a/PanelSwBackendExtension/PanelSwBackendExtension.vcxproj +++ b/src/PanelSwBackendExtension/PanelSwBackendExtension.vcxproj @@ -33,44 +33,36 @@ - $(MSBuildThisFileDirectory)..\poco\Zip\include;$(MSBuildThisFileDirectory)..\poco\Foundation\include;%(AdditionalIncludeDirectories) + ..\7Zap;$(MSBuildThisFileDirectory)..\poco\Zip\include;$(MSBuildThisFileDirectory)..\poco\Foundation\include;%(AdditionalIncludeDirectories) WIN32;_WINDOWS;_USRDLL;EXAMPLECADLL_EXPORTS;FullVersion="$(FullVersion)";%(PreprocessorDefinitions) Use pch.h Level3 + MultiThreaded Version.lib;Shell32.lib;User32.lib;%(AdditionalDependencies) - $(BuildFolderCommon)$(Platform)\poco\lib\$(Configuration);%(AdditionalLibraryDirectories) + $(BuildFolderCommon)$(Platform)\7Zap\lzma-sdk\C\$(Configuration);$(BuildFolderCommon)$(Platform)\poco\lib\$(Configuration);%(AdditionalLibraryDirectories) Windows MachineX86 - - - - - MaxSpeed - true - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - true - ProgramDatabase - - - true - true - true PanelSwBackendExtension.def + + + Create + + + @@ -83,4 +75,14 @@ + + + + + + + + + + diff --git a/src/PanelSwBackendExtension/PanelSwLzmaContainer.cpp b/src/PanelSwBackendExtension/PanelSwLzmaContainer.cpp new file mode 100644 index 00000000..a88a71a0 --- /dev/null +++ b/src/PanelSwBackendExtension/PanelSwLzmaContainer.cpp @@ -0,0 +1,163 @@ +#include "pch.h" +#include "PanelSwLzmaContainer.h" +#pragma comment(lib, "7zC.lib") + +CPanelSwLzmaContainer::~CPanelSwLzmaContainer() +{ + Reset(); +} + +HRESULT CPanelSwLzmaContainer::Reset() +{ + if (_db.get()) + { + SzArEx_Free(_db.get(), &_alloc); + _db.reset(); + } + if (_lookStream.get()) + { + if (_lookStream->buf) + { + ISzAlloc_Free(&_alloc, _lookStream->buf); + } + _lookStream.reset(); + } + if (_archiveStream.get()) + { + File_Close(&_archiveStream->file); + _archiveStream.reset(); + } + if (_outBuffer) + { + ISzAlloc_Free(&_alloc, _outBuffer); + _outBuffer = nullptr; + } + + _fileIndex = -1; + _blockIndex = ~0; + _outBufferSize = 0; + + return S_OK; +} + +HRESULT CPanelSwLzmaContainer::ContainerOpen(LPCWSTR wzContainerId, LPCWSTR wzFilePath) +{ + HRESULT hr = S_OK; + WRes wRes = ERROR_SUCCESS; + SRes sRes = 0; + + _archiveStream.reset(new CFileInStream()); + BextExitOnNull(_archiveStream.get(), hr, E_FAIL, "Failed to create 7zip file stream"); + + _lookStream.reset(new CLookToRead2()); + BextExitOnNull(_archiveStream.get(), hr, E_FAIL, "Failed to create 7zip look stream"); + + _db.reset(new CSzArEx()); + BextExitOnNull(_archiveStream.get(), hr, E_FAIL, "Failed to create 7zip database"); + + wRes = InFile_OpenW(&_archiveStream->file, wzFilePath); + BextExitOnWin32Error(wRes, hr, "Failed to open 7z container '%ls'", wzFilePath); + + FileInStream_CreateVTable(_archiveStream.get()); + _archiveStream->wres = ERROR_SUCCESS; + + LookToRead2_CreateVTable(_lookStream.get(), FALSE); + _lookStream->buf = nullptr; + + _lookStream->buf = (LPBYTE)ISzAlloc_Alloc(&_alloc, _kInputBufSize); + BextExitOnNull(_lookStream->buf, hr, E_FAIL, "Failed to allocate memory"); + + _lookStream->bufSize = _kInputBufSize; + _lookStream->realStream = &_archiveStream->vt; + LookToRead2_INIT(_lookStream.get()); + + CrcGenerateTable(); + + SzArEx_Init(_db.get()); + + sRes = SzArEx_Open(_db.get(), &_lookStream->vt, &_alloc, &_allocTemp); + BextExitOnNull((sRes == SZ_OK), hr, sRes, "Failed to open 7zip database"); + + BextLog(BUNDLE_EXTENSION_LOG_LEVEL_STANDARD, "Openned 7Z container '%ls'", wzFilePath); + +LExit: + return hr; +} + +HRESULT CPanelSwLzmaContainer::ContainerNextStream(BSTR* psczStreamName) +{ + HRESULT hr = S_OK; + LPWSTR szCurrFile = nullptr; + size_t cchName = 0; + + if (psczStreamName && *psczStreamName) + { + ::SysFreeString(*psczStreamName); + *psczStreamName = nullptr; + } + + // Skip folder entries + do + { + ++_fileIndex; + } while ((_fileIndex < _db->NumFiles) && SzArEx_IsDir(_db.get(), _fileIndex)); + if (_fileIndex >= _db->NumFiles) + { + hr = E_NOMOREITEMS; + ExitFunction(); + } + + cchName = SzArEx_GetFileNameUtf16(_db.get(), _fileIndex, nullptr); + BextExitOnNull(cchName, hr, E_FAIL, "File name length is 0"); + + hr = StrAlloc(&szCurrFile, ++cchName); + BextExitOnFailure(hr, "Failed to allocate memory"); + + SzArEx_GetFileNameUtf16(_db.get(), _fileIndex, (UInt16*)szCurrFile); + BextExitOnNull((szCurrFile && *szCurrFile), hr, E_FAIL, "Failed to get file name"); + + if (psczStreamName) + { + *psczStreamName = ::SysAllocString(szCurrFile); + BextExitOnNull(*psczStreamName, hr, E_FAIL, "Failed to allocate sys string"); + } + +LExit: + ReleaseStr(szCurrFile); + return hr; +} + +HRESULT CPanelSwLzmaContainer::ContainerStreamToFile(LPCWSTR wzFileName) +{ + HRESULT hr = S_OK; + SRes sRes = 0; + WRes wRes = ERROR_SUCCESS; + size_t offset = 0; + size_t outSizeProcessed = 0; + + BextExitOnNull((_fileIndex < _db->NumFiles), hr, E_INVALIDSTATE, "7z container is exhausted, can't extract '%ls'", wzFileName); + + sRes = SzArEx_Extract(_db.get(), &_lookStream->vt, _fileIndex, &_blockIndex, &_outBuffer, &_outBufferSize, &offset, &outSizeProcessed, &_alloc, &_allocTemp); + BextExitOnNull((sRes == SZ_OK), hr, sRes, "Failed to open 7zip database"); + + hr = FileWrite(wzFileName, FILE_ATTRIBUTE_NORMAL, _outBuffer + offset, outSizeProcessed, nullptr); + BextExitOnFailure(hr, "Failed to write to file '%ls'", wzFileName); + +LExit: + return hr; +} + +HRESULT CPanelSwLzmaContainer::ContainerStreamToBuffer(BYTE** ppbBuffer, SIZE_T* pcbBuffer) +{ + return E_NOTIMPL; +} + +HRESULT CPanelSwLzmaContainer::ContainerSkipStream() +{ + return S_OK; +} + +HRESULT CPanelSwLzmaContainer::ContainerClose() +{ + return Reset(); +} diff --git a/src/PanelSwBackendExtension/PanelSwLzmaContainer.h b/src/PanelSwBackendExtension/PanelSwLzmaContainer.h new file mode 100644 index 00000000..2f79459f --- /dev/null +++ b/src/PanelSwBackendExtension/PanelSwLzmaContainer.h @@ -0,0 +1,45 @@ +#pragma once +#include "pch.h" +#include "lzma-sdk/C/CpuArch.h" +#include "lzma-sdk/C/7z.h" +#include "lzma-sdk/C/7zAlloc.h" +#include "lzma-sdk/C/7zBuf.h" +#include "lzma-sdk/C/7zCrc.h" +#include "lzma-sdk/C/7zFile.h" +#include "lzma-sdk/C/7zVersion.h" +#include + +class CPanelSwLzmaContainer : public IPanelSwContainer +{ +public: + + ~CPanelSwLzmaContainer(); + + HRESULT ContainerOpen(LPCWSTR wzContainerId, LPCWSTR wzFilePath) override; + + HRESULT ContainerNextStream(BSTR* psczStreamName) override; + + HRESULT ContainerStreamToFile(LPCWSTR wzFileName) override; + + HRESULT ContainerStreamToBuffer(BYTE** ppbBuffer, SIZE_T* pcbBuffer) override; + + HRESULT ContainerSkipStream() override; + + HRESULT ContainerClose() override; + +private: + + HRESULT Reset(); + + std::auto_ptr _archiveStream; + std::auto_ptr _lookStream; + std::auto_ptr _db; + size_t _fileIndex = -1; + UInt32 _blockIndex = ~0; + LPBYTE _outBuffer = nullptr; + size_t _outBufferSize = 0; + + const size_t _kInputBufSize = ((size_t)1 << 18); + const ISzAlloc _alloc = { SzAlloc, SzFree }; + const ISzAlloc _allocTemp = { SzAllocTemp, SzFreeTemp }; +}; diff --git a/PanelSwBackendExtension/PanelSwBackendExtension.cpp b/src/PanelSwBackendExtension/PanelSwZipContainer.cpp similarity index 68% rename from PanelSwBackendExtension/PanelSwBackendExtension.cpp rename to src/PanelSwBackendExtension/PanelSwZipContainer.cpp index 38495e08..39c10ee6 100644 --- a/PanelSwBackendExtension/PanelSwBackendExtension.cpp +++ b/src/PanelSwBackendExtension/PanelSwZipContainer.cpp @@ -1,6 +1,5 @@ #include "pch.h" -#include "PanelSwBackendExtension.h" -#include +#include "PanelSwZipContainer.h" #include "..\poco\Zip\include\Poco\Zip\ZipStream.h" #include "..\poco\Zip\include\Poco\Zip\Compress.h" #include "..\poco\Foundation\include\Poco\UnicodeConverter.h" @@ -14,19 +13,12 @@ using namespace Poco::Zip; using namespace std; -//TODO: Support multiple concurrent containers - -CPanelSwBundleExtension::CPanelSwBundleExtension(IBundleExtensionEngine* pEngine) - : CBextBaseBundleExtension(pEngine) -{ -} - -CPanelSwBundleExtension::~CPanelSwBundleExtension() +CPanelSwZipContainer::~CPanelSwZipContainer() { Reset(); } -HRESULT CPanelSwBundleExtension::Reset() +HRESULT CPanelSwZipContainer::Reset() { HRESULT hr = S_OK; try @@ -55,7 +47,7 @@ HRESULT CPanelSwBundleExtension::Reset() return hr; } -STDMETHODIMP CPanelSwBundleExtension::ContainerOpen(LPCWSTR wzContainerId, LPCWSTR wzFilePath, LPVOID* pContext) +HRESULT CPanelSwZipContainer::ContainerOpen(LPCWSTR wzContainerId, LPCWSTR wzFilePath) { HRESULT hr = S_OK; std::string zipFileA; @@ -91,7 +83,7 @@ STDMETHODIMP CPanelSwBundleExtension::ContainerOpen(LPCWSTR wzContainerId, LPCWS return hr; } -STDMETHODIMP CPanelSwBundleExtension::ContainerNextStream(LPVOID pContext, BSTR* psczStreamName) +HRESULT CPanelSwZipContainer::ContainerNextStream(BSTR* psczStreamName) { HRESULT hr = S_OK; ZipArchive::FileHeaders::const_iterator it; @@ -154,14 +146,13 @@ STDMETHODIMP CPanelSwBundleExtension::ContainerNextStream(LPVOID pContext, BSTR* return hr; } -STDMETHODIMP CPanelSwBundleExtension::ContainerStreamToFile(LPVOID pContext, LPCWSTR wzFileName) +HRESULT CPanelSwZipContainer::ContainerStreamToFile(LPCWSTR wzFileName) { HRESULT hr = S_OK; std::string targetFileA; ZipArchive::FileHeaders::const_iterator it; Poco::UnicodeConverter::toUTF8(wzFileName, targetFileA); - BextLog(BUNDLE_EXTENSION_LOG_LEVEL_STANDARD, "Extracting '%ls'", wzFileName); try { @@ -192,51 +183,17 @@ STDMETHODIMP CPanelSwBundleExtension::ContainerStreamToFile(LPVOID pContext, LPC return hr; } -// Not really needed because it is only used to read the manifest by the engine, and that is always a cab. -STDMETHODIMP CPanelSwBundleExtension::ContainerStreamToBuffer(LPVOID pContext, BYTE** ppbBuffer, SIZE_T* pcbBuffer) +HRESULT CPanelSwZipContainer::ContainerStreamToBuffer(BYTE** ppbBuffer, SIZE_T* pcbBuffer) { return E_NOTIMPL; } -STDMETHODIMP CPanelSwBundleExtension::ContainerSkipStream(LPVOID pContext) +HRESULT CPanelSwZipContainer::ContainerSkipStream() { return S_OK; } -//TODO Release everything in the context -STDMETHODIMP CPanelSwBundleExtension::ContainerClose(LPVOID pContext) +HRESULT CPanelSwZipContainer::ContainerClose() { return Reset(); } - -extern "C" HRESULT WINAPI BundleExtensionCreate( - __in const BUNDLE_EXTENSION_CREATE_ARGS * pArgs, - __inout BUNDLE_EXTENSION_CREATE_RESULTS * pResults -) -{ - HRESULT hr = S_OK; - IBundleExtensionEngine* pEngine = nullptr; - CPanelSwBundleExtension* pExtension = nullptr; - - hr = BextInitializeFromCreateArgs(pArgs, &pEngine); - ExitOnFailure(hr, "Failed to initialize bext"); - - pExtension = new CPanelSwBundleExtension(pEngine); - BextExitOnNull(pExtension, hr, E_OUTOFMEMORY, "Failed to create new CPanelSwBundleExtension."); - - hr = pExtension->Initialize(pArgs); - BextExitOnFailure(hr, "CPanelSwBundleExtension initialization failed."); - - pResults->pfnBundleExtensionProc = BextBaseBundleExtensionProc; - pResults->pvBundleExtensionProcContext = pExtension; - -LExit: - ReleaseObject(pEngine); - - return hr; -} - -extern "C" void WINAPI BundleExtensionDestroy() -{ - BextUninitialize(); -} diff --git a/src/PanelSwBackendExtension/PanelSwZipContainer.h b/src/PanelSwBackendExtension/PanelSwZipContainer.h new file mode 100644 index 00000000..a6e5f1f6 --- /dev/null +++ b/src/PanelSwBackendExtension/PanelSwZipContainer.h @@ -0,0 +1,32 @@ +#pragma once +#include "pch.h" +#include "..\poco\Zip\include\Poco\Zip\ZipArchive.h" +#include +#include + +class CPanelSwZipContainer : public IPanelSwContainer +{ +public: + + ~CPanelSwZipContainer(); + + HRESULT ContainerOpen(LPCWSTR wzContainerId, LPCWSTR wzFilePath) override; + + HRESULT ContainerNextStream(BSTR* psczStreamName) override; + + HRESULT ContainerStreamToFile(LPCWSTR wzFileName) override; + + HRESULT ContainerStreamToBuffer(BYTE** ppbBuffer, SIZE_T* pcbBuffer) override; + + HRESULT ContainerSkipStream() override; + + HRESULT ContainerClose() override; + +private: + + HRESULT Reset(); + + std::auto_ptr _zipStream; + std::auto_ptr _pArchive; + std::string _currFile; +}; diff --git a/PanelSwBackendExtension/framework.h b/src/PanelSwBackendExtension/framework.h similarity index 87% rename from PanelSwBackendExtension/framework.h rename to src/PanelSwBackendExtension/framework.h index 20d97554..701cfd5f 100644 --- a/PanelSwBackendExtension/framework.h +++ b/src/PanelSwBackendExtension/framework.h @@ -7,6 +7,7 @@ #include #include #include +#include // WiX Header Files: #include @@ -15,6 +16,7 @@ #include #include #include +#include #include #include @@ -22,3 +24,4 @@ #include #include #include +#include diff --git a/PanelSwBackendExtension/pch.cpp b/src/PanelSwBackendExtension/pch.cpp similarity index 100% rename from PanelSwBackendExtension/pch.cpp rename to src/PanelSwBackendExtension/pch.cpp diff --git a/PanelSwBackendExtension/pch.h b/src/PanelSwBackendExtension/pch.h similarity index 95% rename from PanelSwBackendExtension/pch.h rename to src/PanelSwBackendExtension/pch.h index 7432f756..f60a4986 100644 --- a/PanelSwBackendExtension/pch.h +++ b/src/PanelSwBackendExtension/pch.h @@ -11,5 +11,6 @@ // add headers that you want to pre-compile here #include "framework.h" +#include "IPanelSwContainer.h" #endif //PCH_H diff --git a/PanelSwCustomActions/AccountNames.cpp b/src/PanelSwCustomActions/AccountNames.cpp similarity index 97% rename from PanelSwCustomActions/AccountNames.cpp rename to src/PanelSwCustomActions/AccountNames.cpp index 0d645a00..e86f17cb 100644 --- a/PanelSwCustomActions/AccountNames.cpp +++ b/src/PanelSwCustomActions/AccountNames.cpp @@ -1,145 +1,145 @@ -#include "pch.h" -#include -#include -#pragma comment (lib, "Advapi32.lib") -using namespace std; - -extern "C" UINT __stdcall AccountNames(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - BOOL bRes = TRUE; - map mapSid2Property; - PSID pSid = nullptr; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - mapSid2Property[SDDL_BUILTIN_ADMINISTRATORS] = L"BUILTIN_ADMINISTRATORS"; - mapSid2Property[SDDL_BUILTIN_GUESTS] = L"BUILTIN_GUESTS"; - mapSid2Property[SDDL_BUILTIN_USERS] = L"BUILTIN_USERS"; - mapSid2Property[SDDL_LOCAL_ADMIN] = L"LOCAL_ADMIN"; - mapSid2Property[SDDL_LOCAL_GUEST] = L"LOCAL_GUEST"; - mapSid2Property[SDDL_ACCOUNT_OPERATORS] = L"ACCOUNT_OPERATORS"; - mapSid2Property[SDDL_BACKUP_OPERATORS] = L"BACKUP_OPERATORS"; - mapSid2Property[SDDL_PRINTER_OPERATORS] = L"PRINTER_OPERATORS"; - mapSid2Property[SDDL_SERVER_OPERATORS] = L"SERVER_OPERATORS"; - mapSid2Property[SDDL_AUTHENTICATED_USERS] = L"AUTHENTICATED_USERS"; - mapSid2Property[SDDL_PERSONAL_SELF] = L"PERSONAL_SELF"; - mapSid2Property[SDDL_CREATOR_OWNER] = L"CREATOR_OWNER"; - mapSid2Property[SDDL_CREATOR_GROUP] = L"CREATOR_GROUP"; - mapSid2Property[SDDL_LOCAL_SYSTEM] = L"LOCAL_SYSTEM"; - mapSid2Property[SDDL_POWER_USERS] = L"POWER_USERS"; - mapSid2Property[SDDL_EVERYONE] = L"EVERYONE"; - mapSid2Property[SDDL_REPLICATOR] = L"REPLICATOR"; - mapSid2Property[SDDL_INTERACTIVE] = L"INTERACTIVE"; - mapSid2Property[SDDL_NETWORK] = L"NETWORK"; - mapSid2Property[SDDL_SERVICE] = L"SERVICE"; - mapSid2Property[SDDL_RESTRICTED_CODE] = L"RESTRICTED_CODE"; - mapSid2Property[SDDL_WRITE_RESTRICTED_CODE] = L"WRITE_RESTRICTED_CODE"; - mapSid2Property[SDDL_ANONYMOUS] = L"ANONYMOUS"; - mapSid2Property[SDDL_SCHEMA_ADMINISTRATORS] = L"SCHEMA_ADMINISTRATORS"; - mapSid2Property[SDDL_CERT_SERV_ADMINISTRATORS] = L"CERT_SERV_ADMINISTRATORS"; - mapSid2Property[SDDL_RAS_SERVERS] = L"RAS_SERVERS"; - mapSid2Property[SDDL_ENTERPRISE_ADMINS] = L"ENTERPRISE_ADMINS"; - mapSid2Property[SDDL_GROUP_POLICY_ADMINS] = L"GROUP_POLICY_ADMINS"; - mapSid2Property[SDDL_ALIAS_PREW2KCOMPACC] = L"ALIAS_PREW2KCOMPACC"; - mapSid2Property[SDDL_LOCAL_SERVICE] = L"LOCAL_SERVICE"; - mapSid2Property[SDDL_NETWORK_SERVICE] = L"NETWORK_SERVICE"; - mapSid2Property[SDDL_REMOTE_DESKTOP] = L"REMOTE_DESKTOP"; - mapSid2Property[SDDL_NETWORK_CONFIGURATION_OPS] = L"NETWORK_CONFIGURATION_OPS"; - mapSid2Property[SDDL_PERFMON_USERS] = L"PERFMON_USERS"; - mapSid2Property[SDDL_PERFLOG_USERS] = L"PERFLOG_USERS"; - mapSid2Property[SDDL_IIS_USERS] = L"IIS_USERS"; - mapSid2Property[SDDL_CRYPTO_OPERATORS] = L"CRYPTO_OPERATORS"; - mapSid2Property[SDDL_OWNER_RIGHTS] = L"OWNER_RIGHTS"; - mapSid2Property[SDDL_EVENT_LOG_READERS] = L"EVENT_LOG_READERS"; - mapSid2Property[SDDL_ENTERPRISE_RO_DCs] = L"ENTERPRISE_RO_DCs"; - mapSid2Property[SDDL_CERTSVC_DCOM_ACCESS] = L"CERTSVC_DCOM_ACCESS"; - mapSid2Property[SDDL_DOMAIN_ADMINISTRATORS] = L"DOMAIN_ADMINISTRATORS"; - mapSid2Property[SDDL_DOMAIN_GUESTS] = L"DOMAIN_GUESTS"; - mapSid2Property[SDDL_DOMAIN_USERS] = L"DOMAIN_USERS"; - mapSid2Property[SDDL_ENTERPRISE_DOMAIN_CONTROLLERS] = L"ENTERPRISE_DOMAIN_CONTROLLERS"; - mapSid2Property[SDDL_DOMAIN_DOMAIN_CONTROLLERS] = L"DOMAIN_DOMAIN_CONTROLLERS"; - mapSid2Property[SDDL_DOMAIN_COMPUTERS] = L"DOMAIN_COMPUTERS"; - - for (const pair &sidPair: mapSid2Property) - { - CWixString accountName; - DWORD dwNameLen = 0; - CWixString domainName; - DWORD dwDomainLen = 0; - SID_NAME_USE eUse; - CWixString fullName; - CWixString property; - - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Converting SID '%ls'", sidPair.first); - bRes = ::ConvertStringSidToSid(sidPair.first, &pSid); - if (!bRes) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Failed converting SID '%ls': Error %u", sidPair.first, ::GetLastError()); - goto LForContinue; - } - - bRes = ::LookupAccountSid(nullptr, pSid, (LPWSTR)accountName, &dwNameLen, (LPWSTR)domainName, &dwDomainLen, &eUse); - if (!bRes && (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Failed getting SID for '%ls': Error %u", sidPair.first, ::GetLastError()); - goto LForContinue; - } - - hr = accountName.Allocate(dwNameLen); - ExitOnFailure(hr, "Failed allocating memory"); - - hr = domainName.Allocate(dwDomainLen); - ExitOnFailure(hr, "Failed allocating memory"); - - bRes = ::LookupAccountSid(nullptr, pSid, (LPWSTR)accountName, &dwNameLen, (LPWSTR)domainName, &dwDomainLen, &eUse); - ExitOnNullWithLastError(bRes, hr, "Failed looking up SID"); - - if (domainName.StrLen() > 0) - { - hr = fullName.Format(L"%ls\\%ls", (LPCWSTR)domainName, (LPCWSTR)accountName); - ExitOnFailure(hr, "Failed formatting string"); - - hr = property.Format(L"%ls_DOMAIN", sidPair.second); - ExitOnFailure(hr, "Failed formatting string"); - - hr = WcaSetProperty(property, (LPCWSTR)domainName); - ExitOnFailure(hr, "Failed setting property"); - } - else - { - hr = fullName.Copy(accountName); - ExitOnFailure(hr, "Failed copying string"); - } - - hr = property.Format(L"%ls_NAME", sidPair.second); - ExitOnFailure(hr, "Failed formatting string"); - - hr = WcaSetProperty(property, (LPCWSTR)accountName); - ExitOnFailure(hr, "Failed setting property"); - - hr = WcaSetProperty(sidPair.second, (LPCWSTR)fullName); - ExitOnFailure(hr, "Failed setting property"); - - LForContinue: - - if (pSid) - { - ::LocalFree(pSid); - pSid = nullptr; - } - } - -LExit: - - if (pSid) - { - ::LocalFree(pSid); - } - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} +#include "pch.h" +#include +#include +#pragma comment (lib, "Advapi32.lib") +using namespace std; + +extern "C" UINT __stdcall AccountNames(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + BOOL bRes = TRUE; + map mapSid2Property; + PSID pSid = nullptr; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + mapSid2Property[SDDL_BUILTIN_ADMINISTRATORS] = L"BUILTIN_ADMINISTRATORS"; + mapSid2Property[SDDL_BUILTIN_GUESTS] = L"BUILTIN_GUESTS"; + mapSid2Property[SDDL_BUILTIN_USERS] = L"BUILTIN_USERS"; + mapSid2Property[SDDL_LOCAL_ADMIN] = L"LOCAL_ADMIN"; + mapSid2Property[SDDL_LOCAL_GUEST] = L"LOCAL_GUEST"; + mapSid2Property[SDDL_ACCOUNT_OPERATORS] = L"ACCOUNT_OPERATORS"; + mapSid2Property[SDDL_BACKUP_OPERATORS] = L"BACKUP_OPERATORS"; + mapSid2Property[SDDL_PRINTER_OPERATORS] = L"PRINTER_OPERATORS"; + mapSid2Property[SDDL_SERVER_OPERATORS] = L"SERVER_OPERATORS"; + mapSid2Property[SDDL_AUTHENTICATED_USERS] = L"AUTHENTICATED_USERS"; + mapSid2Property[SDDL_PERSONAL_SELF] = L"PERSONAL_SELF"; + mapSid2Property[SDDL_CREATOR_OWNER] = L"CREATOR_OWNER"; + mapSid2Property[SDDL_CREATOR_GROUP] = L"CREATOR_GROUP"; + mapSid2Property[SDDL_LOCAL_SYSTEM] = L"LOCAL_SYSTEM"; + mapSid2Property[SDDL_POWER_USERS] = L"POWER_USERS"; + mapSid2Property[SDDL_EVERYONE] = L"EVERYONE"; + mapSid2Property[SDDL_REPLICATOR] = L"REPLICATOR"; + mapSid2Property[SDDL_INTERACTIVE] = L"INTERACTIVE"; + mapSid2Property[SDDL_NETWORK] = L"NETWORK"; + mapSid2Property[SDDL_SERVICE] = L"SERVICE"; + mapSid2Property[SDDL_RESTRICTED_CODE] = L"RESTRICTED_CODE"; + mapSid2Property[SDDL_WRITE_RESTRICTED_CODE] = L"WRITE_RESTRICTED_CODE"; + mapSid2Property[SDDL_ANONYMOUS] = L"ANONYMOUS"; + mapSid2Property[SDDL_SCHEMA_ADMINISTRATORS] = L"SCHEMA_ADMINISTRATORS"; + mapSid2Property[SDDL_CERT_SERV_ADMINISTRATORS] = L"CERT_SERV_ADMINISTRATORS"; + mapSid2Property[SDDL_RAS_SERVERS] = L"RAS_SERVERS"; + mapSid2Property[SDDL_ENTERPRISE_ADMINS] = L"ENTERPRISE_ADMINS"; + mapSid2Property[SDDL_GROUP_POLICY_ADMINS] = L"GROUP_POLICY_ADMINS"; + mapSid2Property[SDDL_ALIAS_PREW2KCOMPACC] = L"ALIAS_PREW2KCOMPACC"; + mapSid2Property[SDDL_LOCAL_SERVICE] = L"LOCAL_SERVICE"; + mapSid2Property[SDDL_NETWORK_SERVICE] = L"NETWORK_SERVICE"; + mapSid2Property[SDDL_REMOTE_DESKTOP] = L"REMOTE_DESKTOP"; + mapSid2Property[SDDL_NETWORK_CONFIGURATION_OPS] = L"NETWORK_CONFIGURATION_OPS"; + mapSid2Property[SDDL_PERFMON_USERS] = L"PERFMON_USERS"; + mapSid2Property[SDDL_PERFLOG_USERS] = L"PERFLOG_USERS"; + mapSid2Property[SDDL_IIS_USERS] = L"IIS_USERS"; + mapSid2Property[SDDL_CRYPTO_OPERATORS] = L"CRYPTO_OPERATORS"; + mapSid2Property[SDDL_OWNER_RIGHTS] = L"OWNER_RIGHTS"; + mapSid2Property[SDDL_EVENT_LOG_READERS] = L"EVENT_LOG_READERS"; + mapSid2Property[SDDL_ENTERPRISE_RO_DCs] = L"ENTERPRISE_RO_DCs"; + mapSid2Property[SDDL_CERTSVC_DCOM_ACCESS] = L"CERTSVC_DCOM_ACCESS"; + mapSid2Property[SDDL_DOMAIN_ADMINISTRATORS] = L"DOMAIN_ADMINISTRATORS"; + mapSid2Property[SDDL_DOMAIN_GUESTS] = L"DOMAIN_GUESTS"; + mapSid2Property[SDDL_DOMAIN_USERS] = L"DOMAIN_USERS"; + mapSid2Property[SDDL_ENTERPRISE_DOMAIN_CONTROLLERS] = L"ENTERPRISE_DOMAIN_CONTROLLERS"; + mapSid2Property[SDDL_DOMAIN_DOMAIN_CONTROLLERS] = L"DOMAIN_DOMAIN_CONTROLLERS"; + mapSid2Property[SDDL_DOMAIN_COMPUTERS] = L"DOMAIN_COMPUTERS"; + + for (const pair &sidPair: mapSid2Property) + { + CWixString accountName; + DWORD dwNameLen = 0; + CWixString domainName; + DWORD dwDomainLen = 0; + SID_NAME_USE eUse; + CWixString fullName; + CWixString property; + + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Converting SID '%ls'", sidPair.first); + bRes = ::ConvertStringSidToSid(sidPair.first, &pSid); + if (!bRes) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Failed converting SID '%ls': Error %u", sidPair.first, ::GetLastError()); + goto LForContinue; + } + + bRes = ::LookupAccountSid(nullptr, pSid, (LPWSTR)accountName, &dwNameLen, (LPWSTR)domainName, &dwDomainLen, &eUse); + if (!bRes && (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Failed getting SID for '%ls': Error %u", sidPair.first, ::GetLastError()); + goto LForContinue; + } + + hr = accountName.Allocate(dwNameLen); + ExitOnFailure(hr, "Failed allocating memory"); + + hr = domainName.Allocate(dwDomainLen); + ExitOnFailure(hr, "Failed allocating memory"); + + bRes = ::LookupAccountSid(nullptr, pSid, (LPWSTR)accountName, &dwNameLen, (LPWSTR)domainName, &dwDomainLen, &eUse); + ExitOnNullWithLastError(bRes, hr, "Failed looking up SID"); + + if (domainName.StrLen() > 0) + { + hr = fullName.Format(L"%ls\\%ls", (LPCWSTR)domainName, (LPCWSTR)accountName); + ExitOnFailure(hr, "Failed formatting string"); + + hr = property.Format(L"%ls_DOMAIN", sidPair.second); + ExitOnFailure(hr, "Failed formatting string"); + + hr = WcaSetProperty(property, (LPCWSTR)domainName); + ExitOnFailure(hr, "Failed setting property"); + } + else + { + hr = fullName.Copy(accountName); + ExitOnFailure(hr, "Failed copying string"); + } + + hr = property.Format(L"%ls_NAME", sidPair.second); + ExitOnFailure(hr, "Failed formatting string"); + + hr = WcaSetProperty(property, (LPCWSTR)accountName); + ExitOnFailure(hr, "Failed setting property"); + + hr = WcaSetProperty(sidPair.second, (LPCWSTR)fullName); + ExitOnFailure(hr, "Failed setting property"); + + LForContinue: + + if (pSid) + { + ::LocalFree(pSid); + pSid = nullptr; + } + } + +LExit: + + if (pSid) + { + ::LocalFree(pSid); + } + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} diff --git a/PanelSwCustomActions/AccountSidSearch.cpp b/src/PanelSwCustomActions/AccountSidSearch.cpp similarity index 100% rename from PanelSwCustomActions/AccountSidSearch.cpp rename to src/PanelSwCustomActions/AccountSidSearch.cpp diff --git a/PanelSwCustomActions/BackupAndRestore.cpp b/src/PanelSwCustomActions/BackupAndRestore.cpp similarity index 100% rename from PanelSwCustomActions/BackupAndRestore.cpp rename to src/PanelSwCustomActions/BackupAndRestore.cpp diff --git a/PanelSwCustomActions/CertificateHashSearch.cpp b/src/PanelSwCustomActions/CertificateHashSearch.cpp similarity index 100% rename from PanelSwCustomActions/CertificateHashSearch.cpp rename to src/PanelSwCustomActions/CertificateHashSearch.cpp diff --git a/PanelSwCustomActions/CheckRebootRequired.cpp b/src/PanelSwCustomActions/CheckRebootRequired.cpp similarity index 100% rename from PanelSwCustomActions/CheckRebootRequired.cpp rename to src/PanelSwCustomActions/CheckRebootRequired.cpp diff --git a/PanelSwCustomActions/CleanPendingFileRenameOperations.cpp b/src/PanelSwCustomActions/CleanPendingFileRenameOperations.cpp similarity index 100% rename from PanelSwCustomActions/CleanPendingFileRenameOperations.cpp rename to src/PanelSwCustomActions/CleanPendingFileRenameOperations.cpp diff --git a/PanelSwCustomActions/CommonDeferred.cpp b/src/PanelSwCustomActions/CommonDeferred.cpp similarity index 96% rename from PanelSwCustomActions/CommonDeferred.cpp rename to src/PanelSwCustomActions/CommonDeferred.cpp index d0eba325..e46a442b 100644 --- a/PanelSwCustomActions/CommonDeferred.cpp +++ b/src/PanelSwCustomActions/CommonDeferred.cpp @@ -1,112 +1,112 @@ -#include "pch.h" -#include "../CaCommon/DeferredActionBase.h" -#include "Telemetry.h" -#include "ShellExecute.h" -#include "FileRegex.h" -#include "FileOperations.h" -#include "TaskScheduler.h" -#include "ExecOnComponent.h" -#include "ServiceConfig.h" -#include "TopShelfService.h" -#include "Unzip.h" -#include "SqlScript.h" -#include "XslTransform.h" -#include "RestartLocalResources.h" -#include "ConcatFiles.h" - -// ReceiverToExecutorFunc implementation. -HRESULT ReceiverToExecutor(LPCSTR szReceiver, CDeferredActionBase** ppExecutor) -{ - HRESULT hr = S_OK; - - (*ppExecutor) = nullptr; - if (0 == ::strcmp(szReceiver, "CTelemetry")) - { - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating Telemetry handler"); - (*ppExecutor) = new CTelemetry(); - } - else if (0 == ::strcmp(szReceiver, "CShellExecute")) - { - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating ShellExecute handler"); - (*ppExecutor) = new CShellExecute(); - } - else if (0 == ::strcmp(szReceiver, "CFileRegex")) - { - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating FileRegex handler"); - (*ppExecutor) = new CFileRegex(); - } - else if (0 == ::strcmp(szReceiver, "CFileOperations")) - { - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating FileOperations handler"); - (*ppExecutor) = new CFileOperations(); - } - else if (0 == ::strcmp(szReceiver, "CTaskScheduler")) - { - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating TaskScheduler handler"); - (*ppExecutor) = new CTaskScheduler(); - } - else if (0 == ::strcmp(szReceiver, "CExecOnComponent")) - { - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating ExecOnComponent handler"); - (*ppExecutor) = new CExecOnComponent(); - } - else if (0 == ::strcmp(szReceiver, "CServiceConfig")) - { - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating ServiceConfig handler"); - (*ppExecutor) = new CServiceConfig(); - } - else if (0 == ::strcmp(szReceiver, "CTopShelfService")) - { - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating TopShelfService handler"); - (*ppExecutor) = new CTopShelfService(); - } - else if (0 == ::strcmp(szReceiver, "CUnzip")) - { - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating Unzip handler"); - (*ppExecutor) = new CUnzip(false); - } - else if (0 == ::strcmp(szReceiver, "CZip")) - { - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating Zip handler"); - (*ppExecutor) = new CUnzip(true); - } - else if (0 == ::strcmp(szReceiver, "CSqlScript")) - { - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating SqlScript handler"); - (*ppExecutor) = new CSqlScript(); - } - else if (0 == ::strcmp(szReceiver, "CXslTransform")) - { - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating XslTransform handler"); - (*ppExecutor) = new CXslTransform(); - } - else if (0 == ::strcmp(szReceiver, "CRestartLocalResources")) - { - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating RestartLocalResources handler"); - (*ppExecutor) = new CRestartLocalResources(); - } - else if (0 == ::strcmp(szReceiver, "CConcatFiles")) - { - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating ConcatFiles handler"); - (*ppExecutor) = new CConcatFiles(); - } - else - { - hr = E_INVALIDARG; - } - - return hr; -} - -extern "C" UINT __stdcall CommonDeferred(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - - hr = CDeferredActionBase::DeferredEntryPoint(hInstall, ReceiverToExecutor); - ExitOnFailure(hr, "Failed to excute CustomActionData command object"); - -LExit : - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} +#include "pch.h" +#include "../CaCommon/DeferredActionBase.h" +#include "Telemetry.h" +#include "ShellExecute.h" +#include "FileRegex.h" +#include "FileOperations.h" +#include "TaskScheduler.h" +#include "ExecOnComponent.h" +#include "ServiceConfig.h" +#include "TopShelfService.h" +#include "Unzip.h" +#include "SqlScript.h" +#include "XslTransform.h" +#include "RestartLocalResources.h" +#include "ConcatFiles.h" + +// ReceiverToExecutorFunc implementation. +HRESULT ReceiverToExecutor(LPCSTR szReceiver, CDeferredActionBase** ppExecutor) +{ + HRESULT hr = S_OK; + + (*ppExecutor) = nullptr; + if (0 == ::strcmp(szReceiver, "CTelemetry")) + { + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating Telemetry handler"); + (*ppExecutor) = new CTelemetry(); + } + else if (0 == ::strcmp(szReceiver, "CShellExecute")) + { + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating ShellExecute handler"); + (*ppExecutor) = new CShellExecute(); + } + else if (0 == ::strcmp(szReceiver, "CFileRegex")) + { + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating FileRegex handler"); + (*ppExecutor) = new CFileRegex(); + } + else if (0 == ::strcmp(szReceiver, "CFileOperations")) + { + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating FileOperations handler"); + (*ppExecutor) = new CFileOperations(); + } + else if (0 == ::strcmp(szReceiver, "CTaskScheduler")) + { + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating TaskScheduler handler"); + (*ppExecutor) = new CTaskScheduler(); + } + else if (0 == ::strcmp(szReceiver, "CExecOnComponent")) + { + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating ExecOnComponent handler"); + (*ppExecutor) = new CExecOnComponent(); + } + else if (0 == ::strcmp(szReceiver, "CServiceConfig")) + { + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating ServiceConfig handler"); + (*ppExecutor) = new CServiceConfig(); + } + else if (0 == ::strcmp(szReceiver, "CTopShelfService")) + { + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating TopShelfService handler"); + (*ppExecutor) = new CTopShelfService(); + } + else if (0 == ::strcmp(szReceiver, "CUnzip")) + { + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating Unzip handler"); + (*ppExecutor) = new CUnzip(false); + } + else if (0 == ::strcmp(szReceiver, "CZip")) + { + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating Zip handler"); + (*ppExecutor) = new CUnzip(true); + } + else if (0 == ::strcmp(szReceiver, "CSqlScript")) + { + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating SqlScript handler"); + (*ppExecutor) = new CSqlScript(); + } + else if (0 == ::strcmp(szReceiver, "CXslTransform")) + { + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating XslTransform handler"); + (*ppExecutor) = new CXslTransform(); + } + else if (0 == ::strcmp(szReceiver, "CRestartLocalResources")) + { + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating RestartLocalResources handler"); + (*ppExecutor) = new CRestartLocalResources(); + } + else if (0 == ::strcmp(szReceiver, "CConcatFiles")) + { + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Creating ConcatFiles handler"); + (*ppExecutor) = new CConcatFiles(); + } + else + { + hr = E_INVALIDARG; + } + + return hr; +} + +extern "C" UINT __stdcall CommonDeferred(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = CDeferredActionBase::DeferredEntryPoint(hInstall, ReceiverToExecutor); + ExitOnFailure(hr, "Failed to excute CustomActionData command object"); + +LExit : + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} diff --git a/PanelSwCustomActions/ConcatFiles.cpp b/src/PanelSwCustomActions/ConcatFiles.cpp similarity index 100% rename from PanelSwCustomActions/ConcatFiles.cpp rename to src/PanelSwCustomActions/ConcatFiles.cpp diff --git a/PanelSwCustomActions/ConcatFiles.h b/src/PanelSwCustomActions/ConcatFiles.h similarity index 100% rename from PanelSwCustomActions/ConcatFiles.h rename to src/PanelSwCustomActions/ConcatFiles.h diff --git a/PanelSwCustomActions/CreateSelfSignCertificate.cpp b/src/PanelSwCustomActions/CreateSelfSignCertificate.cpp similarity index 100% rename from PanelSwCustomActions/CreateSelfSignCertificate.cpp rename to src/PanelSwCustomActions/CreateSelfSignCertificate.cpp diff --git a/PanelSwCustomActions/CustomUninstallKey.cpp b/src/PanelSwCustomActions/CustomUninstallKey.cpp old mode 100755 new mode 100644 similarity index 96% rename from PanelSwCustomActions/CustomUninstallKey.cpp rename to src/PanelSwCustomActions/CustomUninstallKey.cpp index 343d4fa5..bbd188b6 --- a/PanelSwCustomActions/CustomUninstallKey.cpp +++ b/src/PanelSwCustomActions/CustomUninstallKey.cpp @@ -1,269 +1,269 @@ - -#include "pch.h" -#include "CustomUninstallKey.h" -#include "../CaCommon/RegistryKey.h" -#include "RegDataSerializer.h" - -#define CustomUninstallKey_ExecCA L"CustomUninstallKey_deferred" -#define CustomUninstallKey_RollbackCA L"CustomUninstallKey_rollback" -#define CustomUninstallKeyQuery L"SELECT `Id`, `ProductCode`, `Name`, `Data`, `DataType`, `Attributes`, `Condition` FROM `PSW_CustomUninstallKey`" -enum eCustomUninstallKeyQuery { Id = 1, ProductCode, Name, Data, DataType, Attributes, Condition }; - -extern "C" UINT __stdcall CustomUninstallKey_Immediate(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - CCustomUninstallKey data(hInstall); - - hr = WcaInitialize(hInstall, "CustomUninstallKey_Immediate"); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - // Ensure table PSW_CustomUninstallKey exists. - hr = WcaTableExists(L"PSW_CustomUninstallKey"); - ExitOnFailure(hr, "Failed to check if table exists 'PSW_CustomUninstallKey'"); - ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_CustomUninstallKey'. Have you authored 'PanelSw:CustomUninstallKey' entries in WiX code?"); - - hr = data.CreateCustomActionData(); - ExitOnFailure(hr, "Failed"); - -LExit: - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - -extern "C" UINT __stdcall CustomUninstallKey_deferred(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - CCustomUninstallKey data(hInstall); - - hr = WcaInitialize(hInstall, "CustomUninstallKey_deferred"); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - hr = data.Execute(); - ExitOnFailure(hr, "Failed"); - -LExit: - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - -CCustomUninstallKey::CCustomUninstallKey( MSIHANDLE hInstall) - : _hInstall( hInstall) -{ -} - -CCustomUninstallKey::~CCustomUninstallKey(void) -{ -} - -HRESULT CCustomUninstallKey::Execute() -{ - CRegistryXmlParser parser; - LPWSTR customActionData = nullptr; - HRESULT hr = S_OK; - - hr = WcaGetProperty( L"CustomActionData", &customActionData); - ExitOnFailure( hr, "Failed to get CustomActionData"); - WcaLog( LOGLEVEL::LOGMSG_STANDARD, "CustomActionData= '%ls'", customActionData); - - hr = parser.Execute( customActionData); - ExitOnFailure( hr, "Failed to get parse-execute CustomActionData"); - -LExit: - ReleaseStr(customActionData); - return hr; -} - -HRESULT CCustomUninstallKey::CreateCustomActionData() -{ - PMSIHANDLE hView; - PMSIHANDLE hRec; - CRegistryXmlParser xmlParser, xmlRollbackParser; - CComBSTR xmlString = L""; - HRESULT hr = S_OK; - bool bRemoving = false; - LPWSTR pId = nullptr; - LPWSTR szProductCode = nullptr; - LPWSTR pName = nullptr; - LPWSTR pData = nullptr; - LPWSTR pDataType = nullptr; - LPWSTR pCondition = nullptr; - LPWSTR pDataStr = nullptr; - - hr = WcaOpenExecuteView( CustomUninstallKeyQuery, &hView); - ExitOnFailure(hr, "Failed to execute view"); - - if (WcaIsPropertySet("REMOVE")) - { - bRemoving = true; - } - - while ( E_NOMOREITEMS != (hr = WcaFetchRecord(hView, &hRec))) - { - ExitOnFailure(hr, "Failed to fetch record"); - - // Get record. - WCHAR uninstallKey[MAX_PATH]; - CRegDataSerializer dataSer; - int nAttrib; - - hr = WcaGetRecordString( hRec, eCustomUninstallKeyQuery::Id, &pId); - ExitOnFailure(hr, "Failed to get Id"); - hr = WcaGetRecordFormattedString(hRec, eCustomUninstallKeyQuery::ProductCode, &szProductCode); - ExitOnFailure(hr, "Failed to get ProductCode"); - hr = WcaGetRecordString( hRec, eCustomUninstallKeyQuery::Name, &pName); - ExitOnFailure(hr, "Failed to get Name"); - hr = WcaGetRecordString( hRec, eCustomUninstallKeyQuery::Data, &pData); - ExitOnFailure(hr, "Failed to get Data"); - hr = WcaGetRecordString( hRec, eCustomUninstallKeyQuery::DataType, &pDataType); - ExitOnFailure(hr, "Failed to get DataType"); - hr = WcaGetRecordInteger( hRec, eCustomUninstallKeyQuery::Attributes, &nAttrib); - ExitOnFailure(hr, "Failed to get Attributes"); - hr = WcaGetRecordString( hRec, eCustomUninstallKeyQuery::Condition, &pCondition); - ExitOnFailure(hr, "Failed to get Condition"); - - hr = GetUninstallKey(szProductCode, uninstallKey); - ExitOnFailure(hr, "Failed to get uninstall registry key"); - - MSICONDITION cond = ::MsiEvaluateCondition( _hInstall, pCondition); - switch( cond) - { - case MSICONDITION::MSICONDITION_NONE: - case MSICONDITION::MSICONDITION_TRUE: - break; - - case MSICONDITION::MSICONDITION_FALSE: - WcaLog( LOGLEVEL::LOGMSG_STANDARD, "Condition evaluated false for %ls", pId); - continue; - - case MSICONDITION::MSICONDITION_ERROR: - hr = E_FAIL; - ExitOnFailure(hr, "Failed to evaluate condition"); - } - - // Install / UnInstall ? - if (bRemoving) - { - hr = xmlParser.AddDeleteValue(pId, CRegistryKey::RegRoot::LocalMachine, uninstallKey, CRegistryKey::RegArea::Default, pName); - ExitOnFailure(hr, "Failed to create XML element"); - } - else - { - hr = dataSer.Set(pData, pDataType); - ExitOnFailure(hr, "Failed to create parse registry data"); - - hr = dataSer.Serialize(&pDataStr); - ExitOnFailure(hr, "Failed to serialize registry data"); - - hr = xmlParser.AddCreateValue(pId, CRegistryKey::RegRoot::LocalMachine, uninstallKey, CRegistryKey::RegArea::Default, pName, (CRegistryKey::RegValueType)dataSer.DataType(), pDataStr); - ExitOnFailure(hr, "Failed to create XML element"); - } - - hr = CreateRollbackCustomActionData(&xmlRollbackParser, szProductCode, pId, pName); - ExitOnFailure(hr, "Failed to create rollback XML element"); - - ReleaseNullStr(pId); - ReleaseNullStr(szProductCode); - ReleaseNullStr(pName); - ReleaseNullStr(pData); - ReleaseNullStr(pDataType); - ReleaseNullStr(pCondition); - ReleaseNullStr(pDataStr); - } - - hr = xmlRollbackParser.GetXmlString( &xmlString); - ExitOnFailure(hr, "Failed to read XML as text"); - hr = WcaDoDeferredAction( CustomUninstallKey_RollbackCA, xmlString, 0); - ExitOnFailure(hr, "Failed to set property"); - - hr = xmlParser.GetXmlString( &xmlString); - ExitOnFailure(hr, "Failed to read XML as text"); - hr = WcaDoDeferredAction( CustomUninstallKey_ExecCA, xmlString, 0); - ExitOnFailure(hr, "Failed to set property"); - xmlString.Empty(); - -LExit: - ReleaseStr(pId); - ReleaseStr(szProductCode); - ReleaseStr(pName); - ReleaseStr(pData); - ReleaseStr(pDataType); - ReleaseStr(pCondition); - ReleaseStr(pDataStr); - - return hr; -} - -HRESULT CCustomUninstallKey::CreateRollbackCustomActionData(CRegistryXmlParser *pRollbackParser, LPCWSTR szProductCode, LPWSTR pId, LPWSTR pName) -{ - HRESULT hr = S_OK; - CRegistryKey key; - CRegistryKey::RegValueType valType; - BYTE* pDataBytes = nullptr; - LPWSTR pDataStr = nullptr; - DWORD dwSize = 0; - WCHAR keyName[ MAX_PATH]; - CRegDataSerializer dataSer; - - hr = GetUninstallKey(szProductCode, keyName); - ExitOnFailure( hr, "Failed to get Uninstall key"); - - hr = key.Open( CRegistryKey::RegRoot::LocalMachine, keyName, CRegistryKey::RegArea::Default, CRegistryKey::RegAccess::ReadOnly); - if( hr == E_FILENOTFOUND) - { - // Delete key on rollback - hr = pRollbackParser->AddDeleteKey(pId, CRegistryKey::RegRoot::LocalMachine, keyName, CRegistryKey::RegArea::Default); - ExitOnFailure( hr, "Failed to create rollback XML element"); - ExitFunction(); - } - - hr = key.GetValue(pName, &pDataBytes, &valType, &dwSize); - if( hr == E_FILENOTFOUND) - { - // Delete value on rollback - hr = pRollbackParser->AddDeleteValue(pId, CRegistryKey::RegRoot::LocalMachine, keyName, CRegistryKey::RegArea::Default, pName); - ExitOnFailure( hr, "Failed to create rollback XML element"); - ExitFunction(); - } - - hr = dataSer.Set(pDataBytes, valType, dwSize); - ExitOnFailure(hr, "Failed to analyze registry data"); - - hr = dataSer.Serialize(&pDataStr); - ExitOnFailure(hr, "Failed to serialize registry data"); - - hr = pRollbackParser->AddCreateValue(pId, CRegistryKey::RegRoot::LocalMachine, keyName, CRegistryKey::RegArea::Default, pName, valType, pDataStr); - ExitOnFailure( hr, "Failed to create rollback XML element"); - -LExit: - if (pDataBytes) - { - delete[] pDataBytes; - } - - return hr; -} - -HRESULT CCustomUninstallKey::GetUninstallKey(LPCWSTR szProductCode, LPWSTR keyName) -{ - LPWSTR prodCode = nullptr; - HRESULT hr = S_OK; - - if (szProductCode && *szProductCode) - { - prodCode = const_cast(szProductCode); - } - else - { - hr = WcaGetProperty(L"ProductCode", &prodCode); - ExitOnFailure(hr, "Failed to get ProductCode"); - } - - wsprintfW( keyName, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%ls", prodCode); - -LExit: - return hr; -} + +#include "pch.h" +#include "CustomUninstallKey.h" +#include "../CaCommon/RegistryKey.h" +#include "RegDataSerializer.h" + +#define CustomUninstallKey_ExecCA L"CustomUninstallKey_deferred" +#define CustomUninstallKey_RollbackCA L"CustomUninstallKey_rollback" +#define CustomUninstallKeyQuery L"SELECT `Id`, `ProductCode`, `Name`, `Data`, `DataType`, `Attributes`, `Condition` FROM `PSW_CustomUninstallKey`" +enum eCustomUninstallKeyQuery { Id = 1, ProductCode, Name, Data, DataType, Attributes, Condition }; + +extern "C" UINT __stdcall CustomUninstallKey_Immediate(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + CCustomUninstallKey data(hInstall); + + hr = WcaInitialize(hInstall, "CustomUninstallKey_Immediate"); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + // Ensure table PSW_CustomUninstallKey exists. + hr = WcaTableExists(L"PSW_CustomUninstallKey"); + ExitOnFailure(hr, "Failed to check if table exists 'PSW_CustomUninstallKey'"); + ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_CustomUninstallKey'. Have you authored 'PanelSw:CustomUninstallKey' entries in WiX code?"); + + hr = data.CreateCustomActionData(); + ExitOnFailure(hr, "Failed"); + +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +extern "C" UINT __stdcall CustomUninstallKey_deferred(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + CCustomUninstallKey data(hInstall); + + hr = WcaInitialize(hInstall, "CustomUninstallKey_deferred"); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + hr = data.Execute(); + ExitOnFailure(hr, "Failed"); + +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +CCustomUninstallKey::CCustomUninstallKey( MSIHANDLE hInstall) + : _hInstall( hInstall) +{ +} + +CCustomUninstallKey::~CCustomUninstallKey(void) +{ +} + +HRESULT CCustomUninstallKey::Execute() +{ + CRegistryXmlParser parser; + LPWSTR customActionData = nullptr; + HRESULT hr = S_OK; + + hr = WcaGetProperty( L"CustomActionData", &customActionData); + ExitOnFailure( hr, "Failed to get CustomActionData"); + WcaLog( LOGLEVEL::LOGMSG_STANDARD, "CustomActionData= '%ls'", customActionData); + + hr = parser.Execute( customActionData); + ExitOnFailure( hr, "Failed to get parse-execute CustomActionData"); + +LExit: + ReleaseStr(customActionData); + return hr; +} + +HRESULT CCustomUninstallKey::CreateCustomActionData() +{ + PMSIHANDLE hView; + PMSIHANDLE hRec; + CRegistryXmlParser xmlParser, xmlRollbackParser; + CComBSTR xmlString = L""; + HRESULT hr = S_OK; + bool bRemoving = false; + LPWSTR pId = nullptr; + LPWSTR szProductCode = nullptr; + LPWSTR pName = nullptr; + LPWSTR pData = nullptr; + LPWSTR pDataType = nullptr; + LPWSTR pCondition = nullptr; + LPWSTR pDataStr = nullptr; + + hr = WcaOpenExecuteView( CustomUninstallKeyQuery, &hView); + ExitOnFailure(hr, "Failed to execute view"); + + if (WcaIsPropertySet("REMOVE")) + { + bRemoving = true; + } + + while ( E_NOMOREITEMS != (hr = WcaFetchRecord(hView, &hRec))) + { + ExitOnFailure(hr, "Failed to fetch record"); + + // Get record. + WCHAR uninstallKey[MAX_PATH]; + CRegDataSerializer dataSer; + int nAttrib; + + hr = WcaGetRecordString( hRec, eCustomUninstallKeyQuery::Id, &pId); + ExitOnFailure(hr, "Failed to get Id"); + hr = WcaGetRecordFormattedString(hRec, eCustomUninstallKeyQuery::ProductCode, &szProductCode); + ExitOnFailure(hr, "Failed to get ProductCode"); + hr = WcaGetRecordString( hRec, eCustomUninstallKeyQuery::Name, &pName); + ExitOnFailure(hr, "Failed to get Name"); + hr = WcaGetRecordString( hRec, eCustomUninstallKeyQuery::Data, &pData); + ExitOnFailure(hr, "Failed to get Data"); + hr = WcaGetRecordString( hRec, eCustomUninstallKeyQuery::DataType, &pDataType); + ExitOnFailure(hr, "Failed to get DataType"); + hr = WcaGetRecordInteger( hRec, eCustomUninstallKeyQuery::Attributes, &nAttrib); + ExitOnFailure(hr, "Failed to get Attributes"); + hr = WcaGetRecordString( hRec, eCustomUninstallKeyQuery::Condition, &pCondition); + ExitOnFailure(hr, "Failed to get Condition"); + + hr = GetUninstallKey(szProductCode, uninstallKey); + ExitOnFailure(hr, "Failed to get uninstall registry key"); + + MSICONDITION cond = ::MsiEvaluateCondition( _hInstall, pCondition); + switch( cond) + { + case MSICONDITION::MSICONDITION_NONE: + case MSICONDITION::MSICONDITION_TRUE: + break; + + case MSICONDITION::MSICONDITION_FALSE: + WcaLog( LOGLEVEL::LOGMSG_STANDARD, "Condition evaluated false for %ls", pId); + continue; + + case MSICONDITION::MSICONDITION_ERROR: + hr = E_FAIL; + ExitOnFailure(hr, "Failed to evaluate condition"); + } + + // Install / UnInstall ? + if (bRemoving) + { + hr = xmlParser.AddDeleteValue(pId, CRegistryKey::RegRoot::LocalMachine, uninstallKey, CRegistryKey::RegArea::Default, pName); + ExitOnFailure(hr, "Failed to create XML element"); + } + else + { + hr = dataSer.Set(pData, pDataType); + ExitOnFailure(hr, "Failed to create parse registry data"); + + hr = dataSer.Serialize(&pDataStr); + ExitOnFailure(hr, "Failed to serialize registry data"); + + hr = xmlParser.AddCreateValue(pId, CRegistryKey::RegRoot::LocalMachine, uninstallKey, CRegistryKey::RegArea::Default, pName, (CRegistryKey::RegValueType)dataSer.DataType(), pDataStr); + ExitOnFailure(hr, "Failed to create XML element"); + } + + hr = CreateRollbackCustomActionData(&xmlRollbackParser, szProductCode, pId, pName); + ExitOnFailure(hr, "Failed to create rollback XML element"); + + ReleaseNullStr(pId); + ReleaseNullStr(szProductCode); + ReleaseNullStr(pName); + ReleaseNullStr(pData); + ReleaseNullStr(pDataType); + ReleaseNullStr(pCondition); + ReleaseNullStr(pDataStr); + } + + hr = xmlRollbackParser.GetXmlString( &xmlString); + ExitOnFailure(hr, "Failed to read XML as text"); + hr = WcaDoDeferredAction( CustomUninstallKey_RollbackCA, xmlString, 0); + ExitOnFailure(hr, "Failed to set property"); + + hr = xmlParser.GetXmlString( &xmlString); + ExitOnFailure(hr, "Failed to read XML as text"); + hr = WcaDoDeferredAction( CustomUninstallKey_ExecCA, xmlString, 0); + ExitOnFailure(hr, "Failed to set property"); + xmlString.Empty(); + +LExit: + ReleaseStr(pId); + ReleaseStr(szProductCode); + ReleaseStr(pName); + ReleaseStr(pData); + ReleaseStr(pDataType); + ReleaseStr(pCondition); + ReleaseStr(pDataStr); + + return hr; +} + +HRESULT CCustomUninstallKey::CreateRollbackCustomActionData(CRegistryXmlParser *pRollbackParser, LPCWSTR szProductCode, LPWSTR pId, LPWSTR pName) +{ + HRESULT hr = S_OK; + CRegistryKey key; + CRegistryKey::RegValueType valType; + BYTE* pDataBytes = nullptr; + LPWSTR pDataStr = nullptr; + DWORD dwSize = 0; + WCHAR keyName[ MAX_PATH]; + CRegDataSerializer dataSer; + + hr = GetUninstallKey(szProductCode, keyName); + ExitOnFailure( hr, "Failed to get Uninstall key"); + + hr = key.Open( CRegistryKey::RegRoot::LocalMachine, keyName, CRegistryKey::RegArea::Default, CRegistryKey::RegAccess::ReadOnly); + if( hr == E_FILENOTFOUND) + { + // Delete key on rollback + hr = pRollbackParser->AddDeleteKey(pId, CRegistryKey::RegRoot::LocalMachine, keyName, CRegistryKey::RegArea::Default); + ExitOnFailure( hr, "Failed to create rollback XML element"); + ExitFunction(); + } + + hr = key.GetValue(pName, &pDataBytes, &valType, &dwSize); + if( hr == E_FILENOTFOUND) + { + // Delete value on rollback + hr = pRollbackParser->AddDeleteValue(pId, CRegistryKey::RegRoot::LocalMachine, keyName, CRegistryKey::RegArea::Default, pName); + ExitOnFailure( hr, "Failed to create rollback XML element"); + ExitFunction(); + } + + hr = dataSer.Set(pDataBytes, valType, dwSize); + ExitOnFailure(hr, "Failed to analyze registry data"); + + hr = dataSer.Serialize(&pDataStr); + ExitOnFailure(hr, "Failed to serialize registry data"); + + hr = pRollbackParser->AddCreateValue(pId, CRegistryKey::RegRoot::LocalMachine, keyName, CRegistryKey::RegArea::Default, pName, valType, pDataStr); + ExitOnFailure( hr, "Failed to create rollback XML element"); + +LExit: + if (pDataBytes) + { + delete[] pDataBytes; + } + + return hr; +} + +HRESULT CCustomUninstallKey::GetUninstallKey(LPCWSTR szProductCode, LPWSTR keyName) +{ + LPWSTR prodCode = nullptr; + HRESULT hr = S_OK; + + if (szProductCode && *szProductCode) + { + prodCode = const_cast(szProductCode); + } + else + { + hr = WcaGetProperty(L"ProductCode", &prodCode); + ExitOnFailure(hr, "Failed to get ProductCode"); + } + + wsprintfW( keyName, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%ls", prodCode); + +LExit: + return hr; +} diff --git a/PanelSwCustomActions/CustomUninstallKey.h b/src/PanelSwCustomActions/CustomUninstallKey.h old mode 100755 new mode 100644 similarity index 94% rename from PanelSwCustomActions/CustomUninstallKey.h rename to src/PanelSwCustomActions/CustomUninstallKey.h index 9eec9511..c7bf9c87 --- a/PanelSwCustomActions/CustomUninstallKey.h +++ b/src/PanelSwCustomActions/CustomUninstallKey.h @@ -1,31 +1,31 @@ -#pragma once - -#include "pch.h" -#include -#include "RegistryXmlParser.h" - -class CCustomUninstallKey -{ -public: - CCustomUninstallKey( MSIHANDLE hInstall); - virtual ~CCustomUninstallKey(void); - - HRESULT Execute(); - - HRESULT CreateCustomActionData(); - -private: - enum Attributes - { - None = 0, - Write = 1, - Delete = 2 - }; - - HRESULT CreateRollbackCustomActionData( CRegistryXmlParser *pRollbackParser, LPCWSTR szProductCode, LPWSTR pId, LPWSTR pName); - - HRESULT GetUninstallKey(LPCWSTR szProductCode, LPWSTR keyName); - - MSIHANDLE _hInstall; -}; - +#pragma once + +#include "pch.h" +#include +#include "RegistryXmlParser.h" + +class CCustomUninstallKey +{ +public: + CCustomUninstallKey( MSIHANDLE hInstall); + virtual ~CCustomUninstallKey(void); + + HRESULT Execute(); + + HRESULT CreateCustomActionData(); + +private: + enum Attributes + { + None = 0, + Write = 1, + Delete = 2 + }; + + HRESULT CreateRollbackCustomActionData( CRegistryXmlParser *pRollbackParser, LPCWSTR szProductCode, LPWSTR pId, LPWSTR pName); + + HRESULT GetUninstallKey(LPCWSTR szProductCode, LPWSTR keyName); + + MSIHANDLE _hInstall; +}; + diff --git a/PanelSwCustomActions/DiskSpace.cpp b/src/PanelSwCustomActions/DiskSpace.cpp similarity index 100% rename from PanelSwCustomActions/DiskSpace.cpp rename to src/PanelSwCustomActions/DiskSpace.cpp diff --git a/PanelSwCustomActions/DismSched.cpp b/src/PanelSwCustomActions/DismSched.cpp similarity index 100% rename from PanelSwCustomActions/DismSched.cpp rename to src/PanelSwCustomActions/DismSched.cpp diff --git a/PanelSwCustomActions/DllMain.cpp b/src/PanelSwCustomActions/DllMain.cpp similarity index 100% rename from PanelSwCustomActions/DllMain.cpp rename to src/PanelSwCustomActions/DllMain.cpp diff --git a/PanelSwCustomActions/EvaluateExpression.cpp b/src/PanelSwCustomActions/EvaluateExpression.cpp similarity index 100% rename from PanelSwCustomActions/EvaluateExpression.cpp rename to src/PanelSwCustomActions/EvaluateExpression.cpp diff --git a/PanelSwCustomActions/ExecOnComponent.cpp b/src/PanelSwCustomActions/ExecOnComponent.cpp similarity index 100% rename from PanelSwCustomActions/ExecOnComponent.cpp rename to src/PanelSwCustomActions/ExecOnComponent.cpp diff --git a/PanelSwCustomActions/ExecOnComponent.h b/src/PanelSwCustomActions/ExecOnComponent.h similarity index 100% rename from PanelSwCustomActions/ExecOnComponent.h rename to src/PanelSwCustomActions/ExecOnComponent.h diff --git a/PanelSwCustomActions/ExtractPayload.cpp b/src/PanelSwCustomActions/ExtractPayload.cpp similarity index 100% rename from PanelSwCustomActions/ExtractPayload.cpp rename to src/PanelSwCustomActions/ExtractPayload.cpp diff --git a/PanelSwCustomActions/FileOperations.cpp b/src/PanelSwCustomActions/FileOperations.cpp similarity index 100% rename from PanelSwCustomActions/FileOperations.cpp rename to src/PanelSwCustomActions/FileOperations.cpp diff --git a/PanelSwCustomActions/FileOperations.h b/src/PanelSwCustomActions/FileOperations.h similarity index 100% rename from PanelSwCustomActions/FileOperations.h rename to src/PanelSwCustomActions/FileOperations.h diff --git a/PanelSwCustomActions/FileRegex.cpp b/src/PanelSwCustomActions/FileRegex.cpp similarity index 100% rename from PanelSwCustomActions/FileRegex.cpp rename to src/PanelSwCustomActions/FileRegex.cpp diff --git a/PanelSwCustomActions/FileRegex.h b/src/PanelSwCustomActions/FileRegex.h similarity index 100% rename from PanelSwCustomActions/FileRegex.h rename to src/PanelSwCustomActions/FileRegex.h diff --git a/PanelSwCustomActions/FolderPaths.cpp b/src/PanelSwCustomActions/FolderPaths.cpp similarity index 100% rename from PanelSwCustomActions/FolderPaths.cpp rename to src/PanelSwCustomActions/FolderPaths.cpp diff --git a/PanelSwCustomActions/ForceVersion.cpp b/src/PanelSwCustomActions/ForceVersion.cpp similarity index 100% rename from PanelSwCustomActions/ForceVersion.cpp rename to src/PanelSwCustomActions/ForceVersion.cpp diff --git a/PanelSwCustomActions/IsWindowsVersionOrGreater.cpp b/src/PanelSwCustomActions/IsWindowsVersionOrGreater.cpp similarity index 100% rename from PanelSwCustomActions/IsWindowsVersionOrGreater.cpp rename to src/PanelSwCustomActions/IsWindowsVersionOrGreater.cpp diff --git a/PanelSwCustomActions/ListProcessorFeatures.cpp b/src/PanelSwCustomActions/ListProcessorFeatures.cpp similarity index 100% rename from PanelSwCustomActions/ListProcessorFeatures.cpp rename to src/PanelSwCustomActions/ListProcessorFeatures.cpp diff --git a/PanelSwCustomActions/Log.cpp b/src/PanelSwCustomActions/Log.cpp similarity index 96% rename from PanelSwCustomActions/Log.cpp rename to src/PanelSwCustomActions/Log.cpp index ec68e16c..21deb698 100644 --- a/PanelSwCustomActions/Log.cpp +++ b/src/PanelSwCustomActions/Log.cpp @@ -1,67 +1,67 @@ -#include "pch.h" - -#define CustomActionData L"CustomActionData" -#define LogProperty L"LOGMESSAGE" - -extern "C" UINT __stdcall Log(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - LPCWSTR szPropName = LogProperty; - CWixString szMsg; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - - // Deferred? Get CustomActionData - if( ::MsiGetMode( hInstall, MSIRUNMODE_SCHEDULED) - || ::MsiGetMode( hInstall, MSIRUNMODE_COMMIT) - || ::MsiGetMode( hInstall, MSIRUNMODE_ROLLBACK)) - { - szPropName = CustomActionData; - } - - hr = WcaGetProperty( szPropName, (LPWSTR*)szMsg); - ExitOnFailure(hr, "Failed to get property '%ls'", szPropName); - - WcaLog( LOGLEVEL::LOGMSG_STANDARD, "%ls", (LPCWSTR)szMsg); - -LExit: - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - -extern "C" UINT __stdcall Warn(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - LPCWSTR szPropName = LogProperty; - PMSIHANDLE hRecord; - CWixString szMsg; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - - // Deferred? Get CustomActionData - if( ::MsiGetMode( hInstall, MSIRUNMODE_SCHEDULED) - || ::MsiGetMode( hInstall, MSIRUNMODE_COMMIT) - || ::MsiGetMode( hInstall, MSIRUNMODE_ROLLBACK)) - { - szPropName = CustomActionData; - } - - hr = WcaGetProperty( szPropName, (LPWSTR*)szMsg); - ExitOnFailure(hr, "Failed to get property '%ls'", szPropName); - - hRecord = ::MsiCreateRecord( 1); - ExitOnNullWithLastError(hRecord, hr, "Failed to create a warning record."); - - hr = WcaSetRecordString(hRecord, 0, (LPCWSTR)szMsg); - ExitOnFailure(hr, "Failed to set warning record message"); - - WcaProcessMessage( INSTALLMESSAGE::INSTALLMESSAGE_WARNING, hRecord); - -LExit: - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} +#include "pch.h" + +#define CustomActionData L"CustomActionData" +#define LogProperty L"LOGMESSAGE" + +extern "C" UINT __stdcall Log(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + LPCWSTR szPropName = LogProperty; + CWixString szMsg; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + + // Deferred? Get CustomActionData + if( ::MsiGetMode( hInstall, MSIRUNMODE_SCHEDULED) + || ::MsiGetMode( hInstall, MSIRUNMODE_COMMIT) + || ::MsiGetMode( hInstall, MSIRUNMODE_ROLLBACK)) + { + szPropName = CustomActionData; + } + + hr = WcaGetProperty( szPropName, (LPWSTR*)szMsg); + ExitOnFailure(hr, "Failed to get property '%ls'", szPropName); + + WcaLog( LOGLEVEL::LOGMSG_STANDARD, "%ls", (LPCWSTR)szMsg); + +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +extern "C" UINT __stdcall Warn(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + LPCWSTR szPropName = LogProperty; + PMSIHANDLE hRecord; + CWixString szMsg; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + + // Deferred? Get CustomActionData + if( ::MsiGetMode( hInstall, MSIRUNMODE_SCHEDULED) + || ::MsiGetMode( hInstall, MSIRUNMODE_COMMIT) + || ::MsiGetMode( hInstall, MSIRUNMODE_ROLLBACK)) + { + szPropName = CustomActionData; + } + + hr = WcaGetProperty( szPropName, (LPWSTR*)szMsg); + ExitOnFailure(hr, "Failed to get property '%ls'", szPropName); + + hRecord = ::MsiCreateRecord( 1); + ExitOnNullWithLastError(hRecord, hr, "Failed to create a warning record."); + + hr = WcaSetRecordString(hRecord, 0, (LPCWSTR)szMsg); + ExitOnFailure(hr, "Failed to set warning record message"); + + WcaProcessMessage( INSTALLMESSAGE::INSTALLMESSAGE_WARNING, hRecord); + +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} diff --git a/PanelSwCustomActions/Md5Hash.cpp b/src/PanelSwCustomActions/Md5Hash.cpp similarity index 100% rename from PanelSwCustomActions/Md5Hash.cpp rename to src/PanelSwCustomActions/Md5Hash.cpp diff --git a/PanelSwCustomActions/MsiSqlQuery.cpp b/src/PanelSwCustomActions/MsiSqlQuery.cpp similarity index 96% rename from PanelSwCustomActions/MsiSqlQuery.cpp rename to src/PanelSwCustomActions/MsiSqlQuery.cpp index 77412fa6..69df7d5c 100644 --- a/PanelSwCustomActions/MsiSqlQuery.cpp +++ b/src/PanelSwCustomActions/MsiSqlQuery.cpp @@ -1,96 +1,96 @@ -#include "pch.h" - -extern "C" UINT __stdcall MsiSqlQuery(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - PMSIHANDLE hView; - PMSIHANDLE hRecord; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - // Ensure table PSW_XmlSearch exists. - hr = WcaTableExists(L"PSW_MsiSqlQuery"); - ExitOnFailure(hr, "Failed to check if table exists 'PSW_MsiSqlQuery'"); - ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_MsiSqlQuery'. Have you authored 'PanelSw:MsiSqlQuery' entries in WiX code?"); - - // Execute view - hr = WcaOpenExecuteView(L"SELECT `Id`, `Property_`, `Query`, `Condition` FROM `PSW_MsiSqlQuery`", &hView); - ExitOnFailure(hr, "Failed to execute SQL query on 'PSW_MsiSqlQuery'."); - - // Iterate records - while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) - { - ExitOnFailure(hr, "Failed to fetch record."); - - // Get fields - CWixString sId, dstProperty, sQuery, sCondition; - PMSIHANDLE hQueryView; - - hr = WcaGetRecordString(hRecord, 1, (LPWSTR*)sId); - ExitOnFailure(hr, "Failed to get Id."); - hr = WcaGetRecordString(hRecord, 2, (LPWSTR*)dstProperty); - ExitOnFailure(hr, "Failed to get Property_."); - hr = WcaGetRecordFormattedString(hRecord, 3, (LPWSTR*)sQuery); - ExitOnFailure(hr, "Failed to get Query."); - hr = WcaGetRecordString(hRecord, 4, (LPWSTR*)sCondition); - ExitOnFailure(hr, "Failed to get Condition."); - - // Test condition - if (!sCondition.IsNullOrEmpty()) - { - MSICONDITION condRes = ::MsiEvaluateConditionW(hInstall, (LPCWSTR)sCondition); - switch (condRes) - { - case MSICONDITION::MSICONDITION_NONE: - case MSICONDITION::MSICONDITION_TRUE: - WcaLog(LOGMSG_STANDARD, "Condition evaluated to true / none for %ls", (LPCWSTR)sId); - break; - - case MSICONDITION::MSICONDITION_FALSE: - WcaLog(LOGMSG_STANDARD, "Skipping. Condition evaluated to false for %ls", (LPCWSTR)sId); - continue; - - case MSICONDITION::MSICONDITION_ERROR: - hr = E_FAIL; - ExitOnFailure(hr, "Bad Condition field"); - } - } - - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Executing MSI query: %ls", (LPCWSTR)sQuery); - - hr = WcaOpenExecuteView((LPCWSTR)sQuery, &hQueryView); - ExitOnFailure(hr, "Failed executing MSI SQL query %ls", (LPCWSTR)sId); - - // Store result to a property? - if (!dstProperty.IsNullOrEmpty()) - { - PMSIHANDLE hQueryRec; - CWixString value; - - hr = WcaFetchRecord(hQueryView, &hQueryRec); - if (hr == E_NOMOREITEMS) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No results found"); - hr = S_FALSE; - continue; - } - ExitOnFailure(hr, "Failed fetching query result"); - - hr = WcaGetRecordString(hQueryRec, 1, (LPWSTR*)value); - ExitOnFailure(hr, "Failed to get query result."); - - hr = WcaSetProperty(dstProperty, value); - ExitOnFailure(hr, "Failed to set query result to property."); - } - } - - hr = S_OK; - -LExit: - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} +#include "pch.h" + +extern "C" UINT __stdcall MsiSqlQuery(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + PMSIHANDLE hView; + PMSIHANDLE hRecord; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + // Ensure table PSW_XmlSearch exists. + hr = WcaTableExists(L"PSW_MsiSqlQuery"); + ExitOnFailure(hr, "Failed to check if table exists 'PSW_MsiSqlQuery'"); + ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_MsiSqlQuery'. Have you authored 'PanelSw:MsiSqlQuery' entries in WiX code?"); + + // Execute view + hr = WcaOpenExecuteView(L"SELECT `Id`, `Property_`, `Query`, `Condition` FROM `PSW_MsiSqlQuery`", &hView); + ExitOnFailure(hr, "Failed to execute SQL query on 'PSW_MsiSqlQuery'."); + + // Iterate records + while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) + { + ExitOnFailure(hr, "Failed to fetch record."); + + // Get fields + CWixString sId, dstProperty, sQuery, sCondition; + PMSIHANDLE hQueryView; + + hr = WcaGetRecordString(hRecord, 1, (LPWSTR*)sId); + ExitOnFailure(hr, "Failed to get Id."); + hr = WcaGetRecordString(hRecord, 2, (LPWSTR*)dstProperty); + ExitOnFailure(hr, "Failed to get Property_."); + hr = WcaGetRecordFormattedString(hRecord, 3, (LPWSTR*)sQuery); + ExitOnFailure(hr, "Failed to get Query."); + hr = WcaGetRecordString(hRecord, 4, (LPWSTR*)sCondition); + ExitOnFailure(hr, "Failed to get Condition."); + + // Test condition + if (!sCondition.IsNullOrEmpty()) + { + MSICONDITION condRes = ::MsiEvaluateConditionW(hInstall, (LPCWSTR)sCondition); + switch (condRes) + { + case MSICONDITION::MSICONDITION_NONE: + case MSICONDITION::MSICONDITION_TRUE: + WcaLog(LOGMSG_STANDARD, "Condition evaluated to true / none for %ls", (LPCWSTR)sId); + break; + + case MSICONDITION::MSICONDITION_FALSE: + WcaLog(LOGMSG_STANDARD, "Skipping. Condition evaluated to false for %ls", (LPCWSTR)sId); + continue; + + case MSICONDITION::MSICONDITION_ERROR: + hr = E_FAIL; + ExitOnFailure(hr, "Bad Condition field"); + } + } + + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Executing MSI query: %ls", (LPCWSTR)sQuery); + + hr = WcaOpenExecuteView((LPCWSTR)sQuery, &hQueryView); + ExitOnFailure(hr, "Failed executing MSI SQL query %ls", (LPCWSTR)sId); + + // Store result to a property? + if (!dstProperty.IsNullOrEmpty()) + { + PMSIHANDLE hQueryRec; + CWixString value; + + hr = WcaFetchRecord(hQueryView, &hQueryRec); + if (hr == E_NOMOREITEMS) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No results found"); + hr = S_FALSE; + continue; + } + ExitOnFailure(hr, "Failed fetching query result"); + + hr = WcaGetRecordString(hQueryRec, 1, (LPWSTR*)value); + ExitOnFailure(hr, "Failed to get query result."); + + hr = WcaSetProperty(dstProperty, value); + ExitOnFailure(hr, "Failed to set query result to property."); + } + } + + hr = S_OK; + +LExit: + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} diff --git a/PanelSwCustomActions/PanelSwCustomActions.def b/src/PanelSwCustomActions/PanelSwCustomActions.def similarity index 100% rename from PanelSwCustomActions/PanelSwCustomActions.def rename to src/PanelSwCustomActions/PanelSwCustomActions.def diff --git a/PanelSwCustomActions/PanelSwCustomActions.vcxproj b/src/PanelSwCustomActions/PanelSwCustomActions.vcxproj old mode 100755 new mode 100644 similarity index 98% rename from PanelSwCustomActions/PanelSwCustomActions.vcxproj rename to src/PanelSwCustomActions/PanelSwCustomActions.vcxproj index aa8660dc..0b6e0dbd --- a/PanelSwCustomActions/PanelSwCustomActions.vcxproj +++ b/src/PanelSwCustomActions/PanelSwCustomActions.vcxproj @@ -1,193 +1,193 @@ - - - - - - Release - Win32 - - - Release - x64 - - - - native,Version=v0.0 - {0C3A56AA-8073-44E1-8DE4-C257D581BFF0} - PanelSwCustomActions - PanelSwCustomActions - Win32Proj - DynamicLibrary - Unicode - Static - false - false - - - - true - - - - - - - - $(MSBuildThisFileDirectory)..\CaCommon;$(MSBuildThisFileDirectory)..\poco\Zip\include;$(MSBuildThisFileDirectory)..\poco\JSON\include;$(MSBuildThisFileDirectory)..\poco\Foundation\include;$(MSBuildThisFileDirectory)..\protobuf\src;$(IntDir)\..\Protobuf;%(AdditionalIncludeDirectories) - WIN32;_WINDOWS;_USRDLL;EXAMPLECADLL_EXPORTS;FullVersion="$(FullVersion)";%(PreprocessorDefinitions) - Use - pch.h - Level3 - - - CaCommon.lib;libprotobuf-lite.lib;ProtoCaLib.lib;msi.lib;Version.lib;Shell32.lib;User32.lib;%(AdditionalDependencies) - $(OutDir)\..\CaCommon\;$(OutDir)\..\ProtoCaLib;$(BuildFolderCommon)$(Platform)\poco\lib\$(Configuration);$(BuildFolderCommon)$(Platform)\protobuf\$(Configuration);%(AdditionalLibraryDirectories) - Windows - MachineX86 - - - - - MaxSpeed - true - NDEBUG;%(PreprocessorDefinitions) - MultiThreaded - true - ProgramDatabase - - - true - true - true - PanelSwCustomActions.def - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - True - - - - - - - - - - - - - - - - - - - - + + + + + + Release + Win32 + + + Release + x64 + + + + native,Version=v0.0 + {0C3A56AA-8073-44E1-8DE4-C257D581BFF0} + PanelSwCustomActions + PanelSwCustomActions + Win32Proj + DynamicLibrary + Unicode + Static + false + false + + + + true + + + + + + + + $(MSBuildThisFileDirectory)..\CaCommon;$(MSBuildThisFileDirectory)..\poco\Zip\include;$(MSBuildThisFileDirectory)..\poco\JSON\include;$(MSBuildThisFileDirectory)..\poco\Foundation\include;$(MSBuildThisFileDirectory)..\protobuf\src;$(IntDir)\..\Protobuf;%(AdditionalIncludeDirectories) + WIN32;_WINDOWS;_USRDLL;EXAMPLECADLL_EXPORTS;FullVersion="$(FullVersion)";%(PreprocessorDefinitions) + Use + pch.h + Level3 + + + CaCommon.lib;libprotobuf-lite.lib;ProtoCaLib.lib;msi.lib;Version.lib;Shell32.lib;User32.lib;%(AdditionalDependencies) + $(OutDir)\..\CaCommon\;$(OutDir)\..\ProtoCaLib;$(BuildFolderCommon)$(Platform)\poco\lib\$(Configuration);$(BuildFolderCommon)$(Platform)\protobuf\$(Configuration);%(AdditionalLibraryDirectories) + Windows + MachineX86 + + + + + MaxSpeed + true + NDEBUG;%(PreprocessorDefinitions) + MultiThreaded + true + ProgramDatabase + + + true + true + true + PanelSwCustomActions.def + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + + + + + + + + + + + + + + + + + + diff --git a/PanelSwCustomActions/PanelSwCustomActions.vcxproj.filters b/src/PanelSwCustomActions/PanelSwCustomActions.vcxproj.filters old mode 100755 new mode 100644 similarity index 97% rename from PanelSwCustomActions/PanelSwCustomActions.vcxproj.filters rename to src/PanelSwCustomActions/PanelSwCustomActions.vcxproj.filters index 3fa0b16a..0715ab14 --- a/PanelSwCustomActions/PanelSwCustomActions.vcxproj.filters +++ b/src/PanelSwCustomActions/PanelSwCustomActions.vcxproj.filters @@ -1,281 +1,281 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {c0cc41cb-7895-4dcd-a7d3-7c170931e881} - proto - - - {AE664EA9-746D-4D21-87C1-67CAB0333CFD} - pb.h;pb.cc - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Protobuf-Generated - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {c0cc41cb-7895-4dcd-a7d3-7c170931e881} + proto + + + {AE664EA9-746D-4D21-87C1-67CAB0333CFD} + pb.h;pb.cc + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Protobuf-Generated + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + \ No newline at end of file diff --git a/PanelSwCustomActions/PathOperations.cpp b/src/PanelSwCustomActions/PathOperations.cpp similarity index 96% rename from PanelSwCustomActions/PathOperations.cpp rename to src/PanelSwCustomActions/PathOperations.cpp index 57f24b9b..47fa6c1a 100644 --- a/PanelSwCustomActions/PathOperations.cpp +++ b/src/PanelSwCustomActions/PathOperations.cpp @@ -1,126 +1,126 @@ -#include "pch.h" -#include -#include -#pragma comment (lib, "Shlwapi.lib") - -#pragma region SplitPath - -#define PathToSplitProp L"FULL_PATH_TO_SPLIT" -#define SplitDriveProp L"SPLIT_DRIVE" -#define SplitDirectoryProp L"SPLIT_FOLDER" -#define SplitFileNameProp L"SPLIT_FILE_NAME" -#define SplitFileExtProp L"SPLIT_FILE_EXTENSION" - -extern "C" UINT __stdcall SplitPath(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - BOOL bRes = TRUE; - CWixString szFullPath; - WCHAR szDrive[_MAX_DRIVE + 1]; - WCHAR szFolder[_MAX_DIR + 1]; - WCHAR szName[_MAX_FNAME + 1]; - WCHAR szExt[_MAX_EXT + 1]; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - // Get property-to-encrypt name - hr = WcaGetProperty(PathToSplitProp, (LPWSTR*)szFullPath); - ExitOnFailure(hr, "Failed getting %ls", PathToSplitProp); - if (szFullPath.IsNullOrEmpty()) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No path to split..."); - ExitFunction(); - } - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will split property '%ls'", (LPCWSTR)szFullPath); - - er = ::_wsplitpath_s<_MAX_DRIVE + 1, _MAX_DIR + 1, _MAX_FNAME + 1, _MAX_EXT + 1>((LPCWSTR)szFullPath, szDrive, szFolder, szName, szExt); - ExitOnNull( ( er==ERROR_SUCCESS), hr, E_FAIL, "Failed splitting '%ls' full-path", (LPCWSTR)szFullPath); - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Split full path '%ls' to '%ls' '%ls' '%ls' '%ls'", (LPCWSTR)szFullPath, szDrive, szFolder, szName, szExt); - - // Store back in properties - hr = WcaSetProperty(SplitDriveProp, szDrive); - ExitOnFailure(hr, "Failed setting the '%ls'", szDrive); - - hr = WcaSetProperty(SplitDirectoryProp, szFolder); - ExitOnFailure(hr, "Failed setting the '%ls'", szFolder); - - hr = WcaSetProperty(SplitFileNameProp, szName); - ExitOnFailure(hr, "Failed setting the '%ls'", szName); - - hr = WcaSetProperty(SplitFileExtProp, szExt); - ExitOnFailure(hr, "Failed setting the '%ls'", SplitFileExtProp); - -LExit: - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - -#undef PathToSplitProp -#undef SplitDriveProp -#undef SplitDirectoryProp -#undef SplitFileNameProp -#undef SplitFileExtProp - -#pragma endregion - -#pragma region PathExists - -#define PathExistsProp L"FULL_PATH_TO_TEST" -#define PathExistsResultProp L"PATH_EXISTS" - -extern "C" UINT __stdcall PathExists(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - BOOL bRes = TRUE; - CWixString szFullPath; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - // Get full path to test - hr = WcaGetProperty(PathExistsProp, (LPWSTR*)szFullPath); - ExitOnFailure(hr, "Failed getting %ls", PathExistsProp); - if (szFullPath.IsNullOrEmpty()) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No path to test..."); - - hr = WcaSetProperty(PathExistsResultProp, L""); - ExitOnFailure(hr, "Failed setting %ls", PathExistsResultProp); - - ExitFunction(); - } - - // Test if path exists - if (::PathFileExists((LPCWSTR)szFullPath)) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Path '%ls' exists", (LPCWSTR)szFullPath); - - hr = WcaSetIntProperty(PathExistsResultProp, 1); - ExitOnFailure(hr, "Failed setting the '%ls'", PathExistsResultProp); - } - // Doesn't exist. - else - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Path '%ls' does not exist", (LPCWSTR)szFullPath); - - hr = WcaSetProperty(PathExistsResultProp, L""); - ExitOnFailure(hr, "Failed setting %ls", PathExistsResultProp); - } - -LExit: - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - -#undef PathExistsProp -#undef PathExistsResultProp - -#pragma endregion +#include "pch.h" +#include +#include +#pragma comment (lib, "Shlwapi.lib") + +#pragma region SplitPath + +#define PathToSplitProp L"FULL_PATH_TO_SPLIT" +#define SplitDriveProp L"SPLIT_DRIVE" +#define SplitDirectoryProp L"SPLIT_FOLDER" +#define SplitFileNameProp L"SPLIT_FILE_NAME" +#define SplitFileExtProp L"SPLIT_FILE_EXTENSION" + +extern "C" UINT __stdcall SplitPath(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + BOOL bRes = TRUE; + CWixString szFullPath; + WCHAR szDrive[_MAX_DRIVE + 1]; + WCHAR szFolder[_MAX_DIR + 1]; + WCHAR szName[_MAX_FNAME + 1]; + WCHAR szExt[_MAX_EXT + 1]; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + // Get property-to-encrypt name + hr = WcaGetProperty(PathToSplitProp, (LPWSTR*)szFullPath); + ExitOnFailure(hr, "Failed getting %ls", PathToSplitProp); + if (szFullPath.IsNullOrEmpty()) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No path to split..."); + ExitFunction(); + } + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will split property '%ls'", (LPCWSTR)szFullPath); + + er = ::_wsplitpath_s<_MAX_DRIVE + 1, _MAX_DIR + 1, _MAX_FNAME + 1, _MAX_EXT + 1>((LPCWSTR)szFullPath, szDrive, szFolder, szName, szExt); + ExitOnNull( ( er==ERROR_SUCCESS), hr, E_FAIL, "Failed splitting '%ls' full-path", (LPCWSTR)szFullPath); + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Split full path '%ls' to '%ls' '%ls' '%ls' '%ls'", (LPCWSTR)szFullPath, szDrive, szFolder, szName, szExt); + + // Store back in properties + hr = WcaSetProperty(SplitDriveProp, szDrive); + ExitOnFailure(hr, "Failed setting the '%ls'", szDrive); + + hr = WcaSetProperty(SplitDirectoryProp, szFolder); + ExitOnFailure(hr, "Failed setting the '%ls'", szFolder); + + hr = WcaSetProperty(SplitFileNameProp, szName); + ExitOnFailure(hr, "Failed setting the '%ls'", szName); + + hr = WcaSetProperty(SplitFileExtProp, szExt); + ExitOnFailure(hr, "Failed setting the '%ls'", SplitFileExtProp); + +LExit: + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +#undef PathToSplitProp +#undef SplitDriveProp +#undef SplitDirectoryProp +#undef SplitFileNameProp +#undef SplitFileExtProp + +#pragma endregion + +#pragma region PathExists + +#define PathExistsProp L"FULL_PATH_TO_TEST" +#define PathExistsResultProp L"PATH_EXISTS" + +extern "C" UINT __stdcall PathExists(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + BOOL bRes = TRUE; + CWixString szFullPath; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + // Get full path to test + hr = WcaGetProperty(PathExistsProp, (LPWSTR*)szFullPath); + ExitOnFailure(hr, "Failed getting %ls", PathExistsProp); + if (szFullPath.IsNullOrEmpty()) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No path to test..."); + + hr = WcaSetProperty(PathExistsResultProp, L""); + ExitOnFailure(hr, "Failed setting %ls", PathExistsResultProp); + + ExitFunction(); + } + + // Test if path exists + if (::PathFileExists((LPCWSTR)szFullPath)) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Path '%ls' exists", (LPCWSTR)szFullPath); + + hr = WcaSetIntProperty(PathExistsResultProp, 1); + ExitOnFailure(hr, "Failed setting the '%ls'", PathExistsResultProp); + } + // Doesn't exist. + else + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Path '%ls' does not exist", (LPCWSTR)szFullPath); + + hr = WcaSetProperty(PathExistsResultProp, L""); + ExitOnFailure(hr, "Failed setting %ls", PathExistsResultProp); + } + +LExit: + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +#undef PathExistsProp +#undef PathExistsResultProp + +#pragma endregion diff --git a/PanelSwCustomActions/PathSearch.cpp b/src/PanelSwCustomActions/PathSearch.cpp similarity index 100% rename from PanelSwCustomActions/PathSearch.cpp rename to src/PanelSwCustomActions/PathSearch.cpp diff --git a/PanelSwCustomActions/PromptFileDowngrades.cpp b/src/PanelSwCustomActions/PromptFileDowngrades.cpp similarity index 100% rename from PanelSwCustomActions/PromptFileDowngrades.cpp rename to src/PanelSwCustomActions/PromptFileDowngrades.cpp diff --git a/PanelSwCustomActions/ReadIniValues.cpp b/src/PanelSwCustomActions/ReadIniValues.cpp old mode 100755 new mode 100644 similarity index 97% rename from PanelSwCustomActions/ReadIniValues.cpp rename to src/PanelSwCustomActions/ReadIniValues.cpp index 49e4dab0..5855a1e1 --- a/PanelSwCustomActions/ReadIniValues.cpp +++ b/src/PanelSwCustomActions/ReadIniValues.cpp @@ -1,93 +1,93 @@ -#include "pch.h" -#include - -extern "C" UINT __stdcall ReadIniValues(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - PMSIHANDLE hView; - PMSIHANDLE hRecord; - - hr = WcaInitialize(hInstall, "ReadIniValues"); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - // Ensure table PSW_ReadIniValues exists. - hr = WcaTableExists(L"PSW_ReadIniValues"); - ExitOnFailure(hr, "Failed to check if table exists 'PSW_ReadIniValues'"); - ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_ReadIniValues'. Have you authored 'PanelSw:ReadIniValues' entries in WiX code?"); - - // Execute view - hr = WcaOpenExecuteView(L"SELECT `Id`, `FilePath`, `Section`, `Key`, `DestProperty`, `Attributes`, `Condition` FROM `PSW_ReadIniValues`", &hView); - ExitOnFailure(hr, "Failed to execute SQL query on 'ReadIniValues'."); - - // Iterate records - while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) - { - ExitOnFailure(hr, "Failed to fetch record."); - - // Get fields - CWixString szId, szFilePath, szSection, szKey, szDestProperty, szCondition, szValue(1024); - DWORD dwRes = 0; - int bIgnoreErrors = 0; - - hr = WcaGetRecordString(hRecord, 1, (LPWSTR*)szId); - ExitOnFailure(hr, "Failed to get Id."); - hr = WcaGetRecordFormattedString(hRecord, 2, (LPWSTR*)szFilePath); - ExitOnFailure(hr, "Failed to get FilePath."); - hr = WcaGetRecordFormattedString(hRecord, 3, (LPWSTR*)szSection); - ExitOnFailure(hr, "Failed to get Section."); - hr = WcaGetRecordFormattedString(hRecord, 4, (LPWSTR*)szKey); - ExitOnFailure(hr, "Failed to get Key."); - hr = WcaGetRecordString(hRecord, 5, (LPWSTR*)szDestProperty); - ExitOnFailure(hr, "Failed to get DestProperty."); - hr = WcaGetRecordInteger(hRecord, 6, &bIgnoreErrors); - ExitOnFailure(hr, "Failed to get Attributes."); - hr = WcaGetRecordString(hRecord, 7, (LPWSTR*)szCondition); - ExitOnFailure(hr, "Failed to get Condition."); - - // Test condition - MSICONDITION condRes = ::MsiEvaluateConditionW(hInstall, (LPCWSTR)szCondition); - switch (condRes) - { - case MSICONDITION::MSICONDITION_NONE: - case MSICONDITION::MSICONDITION_TRUE: - WcaLog(LOGMSG_STANDARD, "Condition evaluated to true / none."); - break; - - case MSICONDITION::MSICONDITION_FALSE: - WcaLog(LOGMSG_STANDARD, "Skipping. Condition evaluated to false"); - continue; - - case MSICONDITION::MSICONDITION_ERROR: - hr = E_FAIL; - ExitOnFailure(hr, "Bad Condition field"); - } - - // Get the value. - while ((dwRes = ::GetPrivateProfileStringW((LPCWSTR)szSection, (LPCWSTR)szKey, nullptr, (LPWSTR)szValue, szValue.Capacity(), (LPCWSTR)szFilePath)) == (szValue.Capacity() - 1)) - { - hr = szValue.Allocate(2 * szValue.Capacity()); - ExitOnFailure(hr, "Failed allocating memory"); - } - - // Error? - if (dwRes == 0) - { - if (bIgnoreErrors || ((dwRes = ::GetLastError()) == ERROR_SUCCESS)) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Couldn't read value from file '%ls', section '%ls', key '%ls'. Error 0x%08X, ignore = %i", (LPCWSTR)szFilePath, (LPCWSTR)szSection, (LPCWSTR)szKey, dwRes, bIgnoreErrors); - continue; - } - ExitOnNullWithLastError(0, hr, "Failed reading value from '%ls'.", (LPCWSTR)szFilePath); - } - - hr = WcaSetProperty((LPCWSTR)szDestProperty, (LPCWSTR)szValue); - ExitOnFailure(hr, "Failed to set property."); - } - hr = S_OK; - -LExit: - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} +#include "pch.h" +#include + +extern "C" UINT __stdcall ReadIniValues(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + PMSIHANDLE hView; + PMSIHANDLE hRecord; + + hr = WcaInitialize(hInstall, "ReadIniValues"); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + // Ensure table PSW_ReadIniValues exists. + hr = WcaTableExists(L"PSW_ReadIniValues"); + ExitOnFailure(hr, "Failed to check if table exists 'PSW_ReadIniValues'"); + ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_ReadIniValues'. Have you authored 'PanelSw:ReadIniValues' entries in WiX code?"); + + // Execute view + hr = WcaOpenExecuteView(L"SELECT `Id`, `FilePath`, `Section`, `Key`, `DestProperty`, `Attributes`, `Condition` FROM `PSW_ReadIniValues`", &hView); + ExitOnFailure(hr, "Failed to execute SQL query on 'ReadIniValues'."); + + // Iterate records + while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) + { + ExitOnFailure(hr, "Failed to fetch record."); + + // Get fields + CWixString szId, szFilePath, szSection, szKey, szDestProperty, szCondition, szValue(1024); + DWORD dwRes = 0; + int bIgnoreErrors = 0; + + hr = WcaGetRecordString(hRecord, 1, (LPWSTR*)szId); + ExitOnFailure(hr, "Failed to get Id."); + hr = WcaGetRecordFormattedString(hRecord, 2, (LPWSTR*)szFilePath); + ExitOnFailure(hr, "Failed to get FilePath."); + hr = WcaGetRecordFormattedString(hRecord, 3, (LPWSTR*)szSection); + ExitOnFailure(hr, "Failed to get Section."); + hr = WcaGetRecordFormattedString(hRecord, 4, (LPWSTR*)szKey); + ExitOnFailure(hr, "Failed to get Key."); + hr = WcaGetRecordString(hRecord, 5, (LPWSTR*)szDestProperty); + ExitOnFailure(hr, "Failed to get DestProperty."); + hr = WcaGetRecordInteger(hRecord, 6, &bIgnoreErrors); + ExitOnFailure(hr, "Failed to get Attributes."); + hr = WcaGetRecordString(hRecord, 7, (LPWSTR*)szCondition); + ExitOnFailure(hr, "Failed to get Condition."); + + // Test condition + MSICONDITION condRes = ::MsiEvaluateConditionW(hInstall, (LPCWSTR)szCondition); + switch (condRes) + { + case MSICONDITION::MSICONDITION_NONE: + case MSICONDITION::MSICONDITION_TRUE: + WcaLog(LOGMSG_STANDARD, "Condition evaluated to true / none."); + break; + + case MSICONDITION::MSICONDITION_FALSE: + WcaLog(LOGMSG_STANDARD, "Skipping. Condition evaluated to false"); + continue; + + case MSICONDITION::MSICONDITION_ERROR: + hr = E_FAIL; + ExitOnFailure(hr, "Bad Condition field"); + } + + // Get the value. + while ((dwRes = ::GetPrivateProfileStringW((LPCWSTR)szSection, (LPCWSTR)szKey, nullptr, (LPWSTR)szValue, szValue.Capacity(), (LPCWSTR)szFilePath)) == (szValue.Capacity() - 1)) + { + hr = szValue.Allocate(2 * szValue.Capacity()); + ExitOnFailure(hr, "Failed allocating memory"); + } + + // Error? + if (dwRes == 0) + { + if (bIgnoreErrors || ((dwRes = ::GetLastError()) == ERROR_SUCCESS)) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Couldn't read value from file '%ls', section '%ls', key '%ls'. Error 0x%08X, ignore = %i", (LPCWSTR)szFilePath, (LPCWSTR)szSection, (LPCWSTR)szKey, dwRes, bIgnoreErrors); + continue; + } + ExitOnNullWithLastError(0, hr, "Failed reading value from '%ls'.", (LPCWSTR)szFilePath); + } + + hr = WcaSetProperty((LPCWSTR)szDestProperty, (LPCWSTR)szValue); + ExitOnFailure(hr, "Failed to set property."); + } + hr = S_OK; + +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} diff --git a/PanelSwCustomActions/RegDataSerializer.cpp b/src/PanelSwCustomActions/RegDataSerializer.cpp old mode 100755 new mode 100644 similarity index 95% rename from PanelSwCustomActions/RegDataSerializer.cpp rename to src/PanelSwCustomActions/RegDataSerializer.cpp index 18301689..1a068289 --- a/PanelSwCustomActions/RegDataSerializer.cpp +++ b/src/PanelSwCustomActions/RegDataSerializer.cpp @@ -1,213 +1,213 @@ -#include "pch.h" -#include "RegDataSerializer.h" -#include "../CaCommon/RegistryKey.h" -#include -#include -#include - -#define WI_MULTISTRING_NULL L"[~]" -#define WI_MULTISTRING_NULL_SIZE 3 - -CRegDataSerializer::CRegDataSerializer() - :_bytes(nullptr) - , _size(0) - , _bufSize(0) - , _dataType(0) -{ -} - -CRegDataSerializer::~CRegDataSerializer() -{ - Release(); -} - -HRESULT CRegDataSerializer::Release() -{ - if (_bytes) - { - ::free(_bytes); - _bytes = nullptr; - } - - _size = 0; - _bufSize = 0; - _dataType = 0; - - return S_OK; -} - -HRESULT CRegDataSerializer::Allocate(DWORD size) -{ - HRESULT hr = S_OK; - - _size = 0; - if (_bufSize >= size) - { - _size = size; - ExitFunction(); - } - - _bufSize = 0; - _bytes = (BYTE*)realloc(_bytes, size); - ExitOnNull(_bytes, hr, E_INSUFFICIENT_BUFFER, "Failed to allocate buffer"); - - _size = size; - _bufSize = size; - -LExit: - return hr; -} - -HRESULT CRegDataSerializer::Set(const BYTE* pData, DWORD dwDataType, DWORD dwSize) -{ - HRESULT hr = S_OK; - errno_t err; - - hr = Allocate(dwSize); - ExitOnFailure(hr, "Failed to allocate buffer"); - - err = memcpy_s(_bytes, _bufSize, pData, dwSize); - hr = HRESULT_FROM_WIN32(err); - ExitOnFailure(hr, "Failed to copy memory"); - - _size = dwSize; - _dataType = dwDataType; - -LExit: - return hr; -} - -HRESULT CRegDataSerializer::Set(LPCWSTR pDataString, LPCWSTR pDataTypeString) -{ - HRESULT hr = S_OK; - DWORD dwSize = 0; - DWORD dwTmpSize = 0; - LONG lValue = 0; - LONG64 l64Value = 0; - BYTE* pData = nullptr; - LPCWSTR pTmp = nullptr; - CRegistryKey::RegValueType eType; - - hr = CRegistryKey::ParseValueType(pDataTypeString, &eType); - ExitOnFailure(hr, "Failed to parse data type"); - _dataType = eType; - - switch (eType) - { - case CRegistryKey::String: - case CRegistryKey::Expandable: - dwSize = ((1 + wcslen(pDataString)) * sizeof(WCHAR)); - pData = (BYTE*)pDataString; - break; - - case CRegistryKey::MultiString: - pTmp = pDataString; - pData = (BYTE*)pDataString; - while ((dwTmpSize = wcslen(pTmp)) > 0) - { - pTmp += dwTmpSize + 1; - dwTmpSize = ((1 + dwTmpSize) * sizeof(WCHAR)); - dwSize += dwTmpSize; - } - dwSize += sizeof(WCHAR); - break; - - case CRegistryKey::DWord: - lValue = ::wcstol(pDataString, nullptr, 0); - pData = (BYTE*)&lValue; - dwSize = sizeof(lValue); - break; - - case CRegistryKey::QWord: - l64Value = ::_wcstoi64(pDataString, nullptr, 0); - pData = (BYTE*)&l64Value; - dwSize = sizeof(l64Value); - break; - - case CRegistryKey::Binary: - hr = DeSerialize(pDataString, pDataTypeString); - ExitFunction(); - break; - - default: - hr = E_INVALIDARG; - ExitOnFailure(hr, "Invalid registry data type"); - break; - } - - hr = Set(pData, _dataType, dwSize); - ExitOnFailure(hr, "Invalid registry data"); - -LExit: - return hr; -} - -HRESULT CRegDataSerializer::Serialize(LPWSTR* ppDst) const -{ - HRESULT hr = S_OK; - errno_t err = ERROR_SUCCESS; - size_t stStrSize = 0; - int iStrSize = 0; - LPSTR pAnsiStr = nullptr; - - stStrSize = 1 + Base64EncodeGetRequiredLength(_size, ATL_BASE64_FLAG_NOCRLF); - pAnsiStr = (LPSTR)MemAlloc(stStrSize, TRUE); - ExitOnNull(pAnsiStr, hr, NTE_NO_MEMORY, "Failed to allocate memory"); - - iStrSize = stStrSize; - if (!Base64Encode(_bytes, _size, pAnsiStr, &iStrSize, ATL_BASE64_FLAG_NOCRLF)) - { - hr = E_FAIL; - ExitOnFailure(hr, "Failed to encode to base64 string"); - } - - hr = StrAlloc(ppDst, iStrSize); - ExitOnFailure(hr, "Failed to allocate string"); - - err = mbstowcs_s(&stStrSize, (*ppDst), iStrSize, pAnsiStr, iStrSize - 1); - hr = HRESULT_FROM_WIN32(err); - ExitOnFailure(hr, "Failed to convert ansi-string to wide string."); - -LExit: - return hr; -} - -HRESULT CRegDataSerializer::DeSerialize(LPCWSTR pSrc, LPCWSTR sDataType) -{ - HRESULT hr = S_OK; - errno_t err = ERROR_SUCCESS; - size_t iStrSize = 0; - int iMemSize = 0; - LPSTR pAnsiStr = nullptr; - CRegistryKey::RegValueType eType; - - _dataType = ::wcstol(sDataType, nullptr, 10); - hr = CRegistryKey::ParseValueType(sDataType, &eType); - ExitOnFailure(hr, "Failed to parse data type"); - _dataType = eType; - - // Allocate c-string - iStrSize = 1 + wcslen(pSrc); - pAnsiStr = (LPSTR)MemAlloc(iStrSize, TRUE); - ExitOnNull(pAnsiStr, hr, NTE_NO_MEMORY, "Failed to allocate memory"); - - // w-string to c-string - err = ::wcstombs_s(&iStrSize, pAnsiStr, iStrSize, pSrc, (iStrSize - 1) * sizeof(WCHAR)); - hr = HRESULT_FROM_WIN32(err); - ExitOnFailure(hr, "Failed to convert wide-string to ansi-string."); - - iMemSize = 1 + Base64DecodeGetRequiredLength(iStrSize); - hr = Allocate(iMemSize); - ExitOnFailure(hr, "Failed to allocate memory."); - - iMemSize = _bufSize; - if (!Base64Decode(pAnsiStr, iStrSize, _bytes, &iMemSize)) - { - hr = E_FAIL; - ExitOnFailure(hr, "Failed to decode base64 string"); - } - _size = iMemSize; - -LExit: - return hr; -} +#include "pch.h" +#include "RegDataSerializer.h" +#include "../CaCommon/RegistryKey.h" +#include +#include +#include + +#define WI_MULTISTRING_NULL L"[~]" +#define WI_MULTISTRING_NULL_SIZE 3 + +CRegDataSerializer::CRegDataSerializer() + :_bytes(nullptr) + , _size(0) + , _bufSize(0) + , _dataType(0) +{ +} + +CRegDataSerializer::~CRegDataSerializer() +{ + Release(); +} + +HRESULT CRegDataSerializer::Release() +{ + if (_bytes) + { + ::free(_bytes); + _bytes = nullptr; + } + + _size = 0; + _bufSize = 0; + _dataType = 0; + + return S_OK; +} + +HRESULT CRegDataSerializer::Allocate(DWORD size) +{ + HRESULT hr = S_OK; + + _size = 0; + if (_bufSize >= size) + { + _size = size; + ExitFunction(); + } + + _bufSize = 0; + _bytes = (BYTE*)realloc(_bytes, size); + ExitOnNull(_bytes, hr, E_INSUFFICIENT_BUFFER, "Failed to allocate buffer"); + + _size = size; + _bufSize = size; + +LExit: + return hr; +} + +HRESULT CRegDataSerializer::Set(const BYTE* pData, DWORD dwDataType, DWORD dwSize) +{ + HRESULT hr = S_OK; + errno_t err; + + hr = Allocate(dwSize); + ExitOnFailure(hr, "Failed to allocate buffer"); + + err = memcpy_s(_bytes, _bufSize, pData, dwSize); + hr = HRESULT_FROM_WIN32(err); + ExitOnFailure(hr, "Failed to copy memory"); + + _size = dwSize; + _dataType = dwDataType; + +LExit: + return hr; +} + +HRESULT CRegDataSerializer::Set(LPCWSTR pDataString, LPCWSTR pDataTypeString) +{ + HRESULT hr = S_OK; + DWORD dwSize = 0; + DWORD dwTmpSize = 0; + LONG lValue = 0; + LONG64 l64Value = 0; + BYTE* pData = nullptr; + LPCWSTR pTmp = nullptr; + CRegistryKey::RegValueType eType; + + hr = CRegistryKey::ParseValueType(pDataTypeString, &eType); + ExitOnFailure(hr, "Failed to parse data type"); + _dataType = eType; + + switch (eType) + { + case CRegistryKey::String: + case CRegistryKey::Expandable: + dwSize = ((1 + wcslen(pDataString)) * sizeof(WCHAR)); + pData = (BYTE*)pDataString; + break; + + case CRegistryKey::MultiString: + pTmp = pDataString; + pData = (BYTE*)pDataString; + while ((dwTmpSize = wcslen(pTmp)) > 0) + { + pTmp += dwTmpSize + 1; + dwTmpSize = ((1 + dwTmpSize) * sizeof(WCHAR)); + dwSize += dwTmpSize; + } + dwSize += sizeof(WCHAR); + break; + + case CRegistryKey::DWord: + lValue = ::wcstol(pDataString, nullptr, 0); + pData = (BYTE*)&lValue; + dwSize = sizeof(lValue); + break; + + case CRegistryKey::QWord: + l64Value = ::_wcstoi64(pDataString, nullptr, 0); + pData = (BYTE*)&l64Value; + dwSize = sizeof(l64Value); + break; + + case CRegistryKey::Binary: + hr = DeSerialize(pDataString, pDataTypeString); + ExitFunction(); + break; + + default: + hr = E_INVALIDARG; + ExitOnFailure(hr, "Invalid registry data type"); + break; + } + + hr = Set(pData, _dataType, dwSize); + ExitOnFailure(hr, "Invalid registry data"); + +LExit: + return hr; +} + +HRESULT CRegDataSerializer::Serialize(LPWSTR* ppDst) const +{ + HRESULT hr = S_OK; + errno_t err = ERROR_SUCCESS; + size_t stStrSize = 0; + int iStrSize = 0; + LPSTR pAnsiStr = nullptr; + + stStrSize = 1 + Base64EncodeGetRequiredLength(_size, ATL_BASE64_FLAG_NOCRLF); + pAnsiStr = (LPSTR)MemAlloc(stStrSize, TRUE); + ExitOnNull(pAnsiStr, hr, NTE_NO_MEMORY, "Failed to allocate memory"); + + iStrSize = stStrSize; + if (!Base64Encode(_bytes, _size, pAnsiStr, &iStrSize, ATL_BASE64_FLAG_NOCRLF)) + { + hr = E_FAIL; + ExitOnFailure(hr, "Failed to encode to base64 string"); + } + + hr = StrAlloc(ppDst, iStrSize); + ExitOnFailure(hr, "Failed to allocate string"); + + err = mbstowcs_s(&stStrSize, (*ppDst), iStrSize, pAnsiStr, iStrSize - 1); + hr = HRESULT_FROM_WIN32(err); + ExitOnFailure(hr, "Failed to convert ansi-string to wide string."); + +LExit: + return hr; +} + +HRESULT CRegDataSerializer::DeSerialize(LPCWSTR pSrc, LPCWSTR sDataType) +{ + HRESULT hr = S_OK; + errno_t err = ERROR_SUCCESS; + size_t iStrSize = 0; + int iMemSize = 0; + LPSTR pAnsiStr = nullptr; + CRegistryKey::RegValueType eType; + + _dataType = ::wcstol(sDataType, nullptr, 10); + hr = CRegistryKey::ParseValueType(sDataType, &eType); + ExitOnFailure(hr, "Failed to parse data type"); + _dataType = eType; + + // Allocate c-string + iStrSize = 1 + wcslen(pSrc); + pAnsiStr = (LPSTR)MemAlloc(iStrSize, TRUE); + ExitOnNull(pAnsiStr, hr, NTE_NO_MEMORY, "Failed to allocate memory"); + + // w-string to c-string + err = ::wcstombs_s(&iStrSize, pAnsiStr, iStrSize, pSrc, (iStrSize - 1) * sizeof(WCHAR)); + hr = HRESULT_FROM_WIN32(err); + ExitOnFailure(hr, "Failed to convert wide-string to ansi-string."); + + iMemSize = 1 + Base64DecodeGetRequiredLength(iStrSize); + hr = Allocate(iMemSize); + ExitOnFailure(hr, "Failed to allocate memory."); + + iMemSize = _bufSize; + if (!Base64Decode(pAnsiStr, iStrSize, _bytes, &iMemSize)) + { + hr = E_FAIL; + ExitOnFailure(hr, "Failed to decode base64 string"); + } + _size = iMemSize; + +LExit: + return hr; +} diff --git a/PanelSwCustomActions/RegDataSerializer.h b/src/PanelSwCustomActions/RegDataSerializer.h old mode 100755 new mode 100644 similarity index 95% rename from PanelSwCustomActions/RegDataSerializer.h rename to src/PanelSwCustomActions/RegDataSerializer.h index 5caddabb..3647cd15 --- a/PanelSwCustomActions/RegDataSerializer.h +++ b/src/PanelSwCustomActions/RegDataSerializer.h @@ -1,36 +1,36 @@ -#pragma once -#include "pch.h" - -class CRegDataSerializer -{ -public: - CRegDataSerializer(); - virtual ~CRegDataSerializer(); - - HRESULT Set(const BYTE* pData, DWORD dwDataType, DWORD dwSize); - HRESULT Set(LPCWSTR pDataString, LPCWSTR pDataTypeString); - - BYTE* Data() const { return _bytes; } - DWORD Size() const { return _size; } - DWORD DataType() const { return _dataType; } - - HRESULT Serialize(LPWSTR* ppDst) const; - - HRESULT DeSerialize(LPCWSTR pSrc, LPCWSTR sDataType); - - HRESULT Release(); - -private: - - HRESULT Allocate(DWORD size); - - //TODO - HRESULT SerializeMultiString(LPWSTR* pDst) const; - HRESULT DeSerializeMultiString(LPCWSTR pSrc); - - - BYTE* _bytes; - DWORD _size; - DWORD _bufSize; - DWORD _dataType; +#pragma once +#include "pch.h" + +class CRegDataSerializer +{ +public: + CRegDataSerializer(); + virtual ~CRegDataSerializer(); + + HRESULT Set(const BYTE* pData, DWORD dwDataType, DWORD dwSize); + HRESULT Set(LPCWSTR pDataString, LPCWSTR pDataTypeString); + + BYTE* Data() const { return _bytes; } + DWORD Size() const { return _size; } + DWORD DataType() const { return _dataType; } + + HRESULT Serialize(LPWSTR* ppDst) const; + + HRESULT DeSerialize(LPCWSTR pSrc, LPCWSTR sDataType); + + HRESULT Release(); + +private: + + HRESULT Allocate(DWORD size); + + //TODO + HRESULT SerializeMultiString(LPWSTR* pDst) const; + HRESULT DeSerializeMultiString(LPCWSTR pSrc); + + + BYTE* _bytes; + DWORD _size; + DWORD _bufSize; + DWORD _dataType; }; \ No newline at end of file diff --git a/PanelSwCustomActions/RegistryXmlParser.cpp b/src/PanelSwCustomActions/RegistryXmlParser.cpp old mode 100755 new mode 100644 similarity index 96% rename from PanelSwCustomActions/RegistryXmlParser.cpp rename to src/PanelSwCustomActions/RegistryXmlParser.cpp index b42a3f19..388411a5 --- a/PanelSwCustomActions/RegistryXmlParser.cpp +++ b/src/PanelSwCustomActions/RegistryXmlParser.cpp @@ -1,468 +1,468 @@ -#include "pch.h" -#include "RegistryXmlParser.h" -#include "../CaCommon/RegistryKey.h" -#include "RegDataSerializer.h" -#pragma comment( lib, "msxml2.lib") - -CRegistryXmlParser::CRegistryXmlParser() -{ - HRESULT hr = S_OK; - CComPtr pRoot; - IXMLDOMNode* pTmpNode = nullptr; - - hr = ::CoInitialize(nullptr); - ExitOnFailure(hr, "Failed to CoInitialize"); - - // XML docs. - hr = ::CoCreateInstance(CLSID_DOMDocument, nullptr, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&_pXmlDoc); - ExitOnFailure(hr, "Failed to CoCreateInstance CLSID_DOMDocument"); - - // XML root. - hr = _pXmlDoc->createElement(L"Root", &pRoot); - ExitOnFailure(hr, "Failed to create root XML element"); - - // Append root to docs - hr = _pXmlDoc->appendChild(pRoot, &pTmpNode); - ExitOnFailure(hr, "Failed to append root XML element"); - pRoot.Attach((IXMLDOMElement*)pTmpNode); - -LExit: - return; -} - -CRegistryXmlParser::~CRegistryXmlParser() -{ - _pXmlDoc.Release(); - - ::CoUninitialize(); -} - -HRESULT CRegistryXmlParser::GetXmlString(BSTR* ppString) -{ - HRESULT hr = S_OK; - - hr = _pXmlDoc->get_xml(ppString); - ExitOnFailure(hr, "Failed to get XML string"); - -LExit: - return hr; -} - -HRESULT CRegistryXmlParser::AddDeleteKey(WCHAR* pId, CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area) -{ - HRESULT hr = S_OK; - CComPtr xmlElem, xmlRoot; - CComPtr tmpNode; - CComPtr xmlDoc; - CComBSTR attName = L""; - CComVariant value; - - hr = _pXmlDoc->get_documentElement(&xmlRoot); - ExitOnFailure(hr, "Failed to get XML root"); - - hr = _pXmlDoc->createElement(L"DeleteKey", &xmlElem); - ExitOnFailure(hr, "Failed to create XML element"); - - attName = "Id"; - value = pId; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - attName = "Root"; - value = (DWORD)root; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - attName = "Key"; - value = subkeyName; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - if (area == CRegistryKey::RegArea::Default) - { - hr = CRegistryKey::GetDefaultArea(&area); - ExitOnFailure(hr, "Failed to get default registry area"); - } - - attName = "Area"; - value = area; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - hr = xmlRoot->appendChild(xmlElem, &tmpNode); - tmpNode.Release(); - ExitOnFailure(hr, "Failed to append XML element"); - -LExit: - return hr; -} - -HRESULT CRegistryXmlParser::AddDeleteValue(WCHAR* pId, CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area, WCHAR* valName) -{ - HRESULT hr = S_OK; - CComPtr xmlElem, xmlRoot; - CComPtr tmpNode; - CComBSTR attName = L""; - CComVariant value; - - hr = _pXmlDoc->get_documentElement(&xmlRoot); - ExitOnFailure(hr, "Failed to get XML root"); - - hr = _pXmlDoc->createElement(L"DeleteValue", &xmlElem); - ExitOnFailure(hr, "Failed to create XML element"); - - attName = "Id"; - value = pId; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - attName = "Root"; - value = (DWORD)root; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - attName = "Key"; - value = subkeyName; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - if (area == CRegistryKey::RegArea::Default) - { - hr = CRegistryKey::GetDefaultArea(&area); - ExitOnFailure(hr, "Failed to get default registry area"); - } - - attName = "Area"; - value = area; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - attName = "Name"; - value = valName; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - hr = xmlRoot->appendChild(xmlElem, &tmpNode); - tmpNode.Release(); - ExitOnFailure(hr, "Failed to append XML element"); - -LExit: - return hr; -} - -HRESULT CRegistryXmlParser::AddCreateKey(WCHAR* pId, CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area) -{ - HRESULT hr = S_OK; - CComPtr xmlElem, xmlRoot; - CComPtr tmpNode; - CComBSTR attName = L""; - CComVariant value; - - hr = _pXmlDoc->get_documentElement(&xmlRoot); - ExitOnFailure(hr, "Failed to get XML root"); - - hr = _pXmlDoc->createElement(L"CreateKey", &xmlElem); - ExitOnFailure(hr, "Failed to create XML element"); - - attName = "Id"; - value = pId; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - attName = "Root"; - value = (DWORD)root; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - attName = "Key"; - value = subkeyName; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - if (area == CRegistryKey::RegArea::Default) - { - hr = CRegistryKey::GetDefaultArea(&area); - ExitOnFailure(hr, "Failed to get default registry area"); - } - - attName = "Area"; - value = area; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - hr = xmlRoot->appendChild(xmlElem, &tmpNode); - tmpNode.Release(); - ExitOnFailure(hr, "Failed to append XML element"); - -LExit: - return hr; -} - -HRESULT CRegistryXmlParser::AddCreateValue(WCHAR* pId, CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area, WCHAR* valName, CRegistryKey::RegValueType valType, WCHAR* pData) -{ - HRESULT hr = S_OK; - CComPtr xmlElem, xmlRoot; - CComPtr tmpNode; - CComBSTR attName = L""; - CComVariant value; - void* pArrayData = nullptr; - - hr = _pXmlDoc->get_documentElement(&xmlRoot); - ExitOnFailure(hr, "Failed to get XML root"); - - hr = _pXmlDoc->createElement(L"CreateValue", &xmlElem); - ExitOnFailure(hr, "Failed to create XML element"); - - attName = "Id"; - value = pId; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - attName = "Root"; - value = (DWORD)root; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - attName = "Key"; - value = subkeyName; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - if (area == CRegistryKey::RegArea::Default) - { - hr = CRegistryKey::GetDefaultArea(&area); - ExitOnFailure(hr, "Failed to get default registry area"); - } - - attName = "Area"; - value = area; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - attName = "Name"; - value = valName; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - attName = "Type"; - value = valType; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - attName = "Data"; - value = pData; - hr = xmlElem->setAttribute(attName, value); - ExitOnFailure(hr, "Failed to set XML attribute"); - - hr = xmlRoot->appendChild(xmlElem, &tmpNode); - tmpNode.Release(); - ExitOnFailure(hr, "Failed to append XML element"); - -LExit: - return hr; -} - -HRESULT CRegistryXmlParser::Execute(WCHAR* pCustomActionData) -{ - HRESULT hr = S_OK; - CComPtr pXmlDoc; - CComPtr pNodes; - IXMLDOMNodeList* pTmpNodes = nullptr; - IXMLDOMNode* pTmpNode = nullptr; - IXMLDOMElement* pCurrElem = nullptr; - VARIANT_BOOL isXmlSuccess; - LONG nodeCount = 0; - DOMNodeType nodeType; - - // XML docs. - hr = ::CoCreateInstance(CLSID_DOMDocument, nullptr, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pXmlDoc); - ExitOnFailure(hr, "Failed to CoCreateInstance CLSID_DOMDocument"); - - hr = pXmlDoc->loadXML(pCustomActionData, &isXmlSuccess); - ExitOnFailure(hr, "Failed to load XML"); - if (!isXmlSuccess) - { - hr = E_FAIL; - ExitOnFailure(hr, "Failed to load XML"); - } - - hr = pXmlDoc->selectNodes(CComBSTR(L"/Root/*"), &pTmpNodes); - ExitOnFailure(hr, "Failed to select XML nodes"); - ExitOnNull(pTmpNodes, hr, E_FAIL, "Failed to select XML nodes"); - pNodes.Attach(pTmpNodes); - - hr = pNodes->get_length(&nodeCount); - ExitOnFailure(hr, "Failed to get node count"); - - for (LONG i = 0; i < nodeCount; ++i) - { - pTmpNode = nullptr; - - hr = pNodes->get_item(i, &pTmpNode); - ExitOnFailure(hr, "Failed to get node"); - ExitOnNull(pTmpNode, hr, E_FAIL, "Failed to get node"); - - hr = pTmpNode->get_nodeType(&nodeType); - ExitOnFailure(hr, "Failed to get node type"); - if (nodeType != DOMNodeType::NODE_ELEMENT) - { - hr = E_FAIL; - ExitOnFailure(hr, "Expected an element"); - } - - hr = pTmpNode->QueryInterface(IID_IXMLDOMElement, (void**)&pCurrElem); - ExitOnFailure(hr, "Failed quering as IID_IXMLDOMElement"); - ExitOnNull(pCurrElem, hr, E_FAIL, "Failed to get IID_IXMLDOMElement"); - - hr = XmlExecute(pCurrElem); - ExitOnFailure(hr, "Failed to parse-execute XML element"); - } - -LExit: - return hr; -} - -HRESULT CRegistryXmlParser::XmlExecute(IXMLDOMElement* xmlElem) -{ - HRESULT hr = S_OK; - CComBSTR tag; - CComVariant id, root, key, valName, valType, valData, area; - DWORD dwArea, dwRoot; - BYTE* pData = nullptr; - CRegDataSerializer regDataSer; - - // Get common fields. - hr = xmlElem->get_tagName(&tag); - ExitOnFailure(hr, "Failed to get XML tag name"); - hr = xmlElem->getAttribute(CComBSTR("Id"), &id); - ExitOnFailure(hr, "Failed to get XML Id attribute"); - hr = xmlElem->getAttribute(CComBSTR("Root"), &root); - ExitOnFailure(hr, "Failed to get XML Root attribute"); - hr = xmlElem->getAttribute(CComBSTR("Key"), &key); - ExitOnFailure(hr, "Failed to get XML Key attribute"); - hr = xmlElem->getAttribute(CComBSTR("Area"), &area); - ExitOnFailure(hr, "Failed to get XML Area attribute"); - - Bstr2Dword(root, (DWORD*)&dwRoot); - Bstr2Dword(area, (DWORD*)&dwArea); - - if (wcscmp(tag, L"DeleteKey") == 0) - { - hr = DeleteKey((CRegistryKey::RegRoot)dwRoot, key.bstrVal, (CRegistryKey::RegArea)dwArea); - ExitOnFailure(hr, "Failed to delete key '%ls', root '%i', area '%i'", key.bstrVal, dwRoot, dwArea); - ExitFunction(); - } - else if (wcscmp(tag, L"CreateKey") == 0) - { - hr = CreateKey((CRegistryKey::RegRoot)dwRoot, key.bstrVal, (CRegistryKey::RegArea)dwArea); - ExitOnFailure(hr, "Failed to create key"); - ExitFunction(); - } - else if (wcscmp(tag, L"DeleteValue") == 0) - { - hr = xmlElem->getAttribute(CComBSTR("Name"), &valName); - ExitOnFailure(hr, "Failed to get XML Name attribute"); - - hr = DeleteValue((CRegistryKey::RegRoot)dwRoot, key.bstrVal, (CRegistryKey::RegArea)dwArea, valName.bstrVal); - ExitOnFailure(hr, "Failed to create key"); - ExitFunction(); - } - else if (wcscmp(tag, L"CreateValue") == 0) - { - hr = xmlElem->getAttribute(CComBSTR("Name"), &valName); - ExitOnFailure(hr, "Failed to get XML Name attribute"); - hr = xmlElem->getAttribute(CComBSTR("Type"), &valType); - ExitOnFailure(hr, "Failed to get XML Type attribute"); - hr = xmlElem->getAttribute(CComBSTR("Data"), &valData); - ExitOnFailure(hr, "Failed to get XML Data attribute"); - - hr = regDataSer.DeSerialize(valData.bstrVal, valType.bstrVal); - ExitOnFailure(hr, "Failed to desrialize registry data"); - - hr = CreateValue( - (CRegistryKey::RegRoot)dwRoot - , key.bstrVal - , (CRegistryKey::RegArea)dwArea - , valName.bstrVal - , regDataSer.DataType() - , regDataSer.Data() - , regDataSer.Size()); - ExitOnFailure(hr, "Failed to create value"); - - ExitFunction(); - } - -LExit: - return hr; -} - -HRESULT CRegistryXmlParser::Bstr2Dword(VARIANT str, DWORD* dwVal) -{ - (*dwVal) = _wtol(str.bstrVal); - return S_OK; -} - -HRESULT CRegistryXmlParser::DeleteKey(CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area) -{ - CRegistryKey regKey; - HRESULT hr; - - hr = regKey.Open(root, subkeyName, (CRegistryKey::RegArea)area, CRegistryKey::RegAccess::All); - if (hr == E_FILENOTFOUND) - { - return S_OK; - } - ExitOnFailure(hr, "Failed to open registry key"); - - hr = regKey.Delete(); - ExitOnFailure(hr, "Failed to delete registry key"); - -LExit: - return hr; -} - -HRESULT CRegistryXmlParser::CreateKey(CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area) -{ - CRegistryKey regKey; - HRESULT hr; - - hr = regKey.Create(root, subkeyName, (CRegistryKey::RegArea)area, CRegistryKey::RegAccess::All); - ExitOnFailure(hr, "Failed to create registry key"); - -LExit: - return hr; -} - -HRESULT CRegistryXmlParser::DeleteValue(CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area, WCHAR* valName) -{ - CRegistryKey regKey; - HRESULT hr; - - hr = regKey.Open(root, subkeyName, (CRegistryKey::RegArea)area, CRegistryKey::RegAccess::All); - if (hr == E_FILENOTFOUND) - { - return S_OK; - } - ExitOnFailure(hr, "Failed to open registry key"); - - hr = regKey.DeleteValue(valName); - ExitOnFailure(hr, "Failed to open registry value"); - -LExit: - return hr; -} - -HRESULT CRegistryXmlParser::CreateValue(CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area, WCHAR* valName, DWORD valType, BYTE* valData, DWORD dataSize) -{ - CRegistryKey regKey; - HRESULT hr; - - hr = regKey.Create(root, subkeyName, (CRegistryKey::RegArea)area, CRegistryKey::RegAccess::All); - ExitOnFailure(hr, "Failed to create registry key"); - - hr = regKey.SetValue(valName, (CRegistryKey::RegValueType)valType, valData, dataSize); - ExitOnFailure(hr, "Failed to create registry value"); - -LExit: - return hr; -} +#include "pch.h" +#include "RegistryXmlParser.h" +#include "../CaCommon/RegistryKey.h" +#include "RegDataSerializer.h" +#pragma comment( lib, "msxml2.lib") + +CRegistryXmlParser::CRegistryXmlParser() +{ + HRESULT hr = S_OK; + CComPtr pRoot; + IXMLDOMNode* pTmpNode = nullptr; + + hr = ::CoInitialize(nullptr); + ExitOnFailure(hr, "Failed to CoInitialize"); + + // XML docs. + hr = ::CoCreateInstance(CLSID_DOMDocument, nullptr, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&_pXmlDoc); + ExitOnFailure(hr, "Failed to CoCreateInstance CLSID_DOMDocument"); + + // XML root. + hr = _pXmlDoc->createElement(L"Root", &pRoot); + ExitOnFailure(hr, "Failed to create root XML element"); + + // Append root to docs + hr = _pXmlDoc->appendChild(pRoot, &pTmpNode); + ExitOnFailure(hr, "Failed to append root XML element"); + pRoot.Attach((IXMLDOMElement*)pTmpNode); + +LExit: + return; +} + +CRegistryXmlParser::~CRegistryXmlParser() +{ + _pXmlDoc.Release(); + + ::CoUninitialize(); +} + +HRESULT CRegistryXmlParser::GetXmlString(BSTR* ppString) +{ + HRESULT hr = S_OK; + + hr = _pXmlDoc->get_xml(ppString); + ExitOnFailure(hr, "Failed to get XML string"); + +LExit: + return hr; +} + +HRESULT CRegistryXmlParser::AddDeleteKey(WCHAR* pId, CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area) +{ + HRESULT hr = S_OK; + CComPtr xmlElem, xmlRoot; + CComPtr tmpNode; + CComPtr xmlDoc; + CComBSTR attName = L""; + CComVariant value; + + hr = _pXmlDoc->get_documentElement(&xmlRoot); + ExitOnFailure(hr, "Failed to get XML root"); + + hr = _pXmlDoc->createElement(L"DeleteKey", &xmlElem); + ExitOnFailure(hr, "Failed to create XML element"); + + attName = "Id"; + value = pId; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + attName = "Root"; + value = (DWORD)root; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + attName = "Key"; + value = subkeyName; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + if (area == CRegistryKey::RegArea::Default) + { + hr = CRegistryKey::GetDefaultArea(&area); + ExitOnFailure(hr, "Failed to get default registry area"); + } + + attName = "Area"; + value = area; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + hr = xmlRoot->appendChild(xmlElem, &tmpNode); + tmpNode.Release(); + ExitOnFailure(hr, "Failed to append XML element"); + +LExit: + return hr; +} + +HRESULT CRegistryXmlParser::AddDeleteValue(WCHAR* pId, CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area, WCHAR* valName) +{ + HRESULT hr = S_OK; + CComPtr xmlElem, xmlRoot; + CComPtr tmpNode; + CComBSTR attName = L""; + CComVariant value; + + hr = _pXmlDoc->get_documentElement(&xmlRoot); + ExitOnFailure(hr, "Failed to get XML root"); + + hr = _pXmlDoc->createElement(L"DeleteValue", &xmlElem); + ExitOnFailure(hr, "Failed to create XML element"); + + attName = "Id"; + value = pId; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + attName = "Root"; + value = (DWORD)root; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + attName = "Key"; + value = subkeyName; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + if (area == CRegistryKey::RegArea::Default) + { + hr = CRegistryKey::GetDefaultArea(&area); + ExitOnFailure(hr, "Failed to get default registry area"); + } + + attName = "Area"; + value = area; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + attName = "Name"; + value = valName; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + hr = xmlRoot->appendChild(xmlElem, &tmpNode); + tmpNode.Release(); + ExitOnFailure(hr, "Failed to append XML element"); + +LExit: + return hr; +} + +HRESULT CRegistryXmlParser::AddCreateKey(WCHAR* pId, CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area) +{ + HRESULT hr = S_OK; + CComPtr xmlElem, xmlRoot; + CComPtr tmpNode; + CComBSTR attName = L""; + CComVariant value; + + hr = _pXmlDoc->get_documentElement(&xmlRoot); + ExitOnFailure(hr, "Failed to get XML root"); + + hr = _pXmlDoc->createElement(L"CreateKey", &xmlElem); + ExitOnFailure(hr, "Failed to create XML element"); + + attName = "Id"; + value = pId; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + attName = "Root"; + value = (DWORD)root; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + attName = "Key"; + value = subkeyName; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + if (area == CRegistryKey::RegArea::Default) + { + hr = CRegistryKey::GetDefaultArea(&area); + ExitOnFailure(hr, "Failed to get default registry area"); + } + + attName = "Area"; + value = area; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + hr = xmlRoot->appendChild(xmlElem, &tmpNode); + tmpNode.Release(); + ExitOnFailure(hr, "Failed to append XML element"); + +LExit: + return hr; +} + +HRESULT CRegistryXmlParser::AddCreateValue(WCHAR* pId, CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area, WCHAR* valName, CRegistryKey::RegValueType valType, WCHAR* pData) +{ + HRESULT hr = S_OK; + CComPtr xmlElem, xmlRoot; + CComPtr tmpNode; + CComBSTR attName = L""; + CComVariant value; + void* pArrayData = nullptr; + + hr = _pXmlDoc->get_documentElement(&xmlRoot); + ExitOnFailure(hr, "Failed to get XML root"); + + hr = _pXmlDoc->createElement(L"CreateValue", &xmlElem); + ExitOnFailure(hr, "Failed to create XML element"); + + attName = "Id"; + value = pId; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + attName = "Root"; + value = (DWORD)root; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + attName = "Key"; + value = subkeyName; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + if (area == CRegistryKey::RegArea::Default) + { + hr = CRegistryKey::GetDefaultArea(&area); + ExitOnFailure(hr, "Failed to get default registry area"); + } + + attName = "Area"; + value = area; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + attName = "Name"; + value = valName; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + attName = "Type"; + value = valType; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + attName = "Data"; + value = pData; + hr = xmlElem->setAttribute(attName, value); + ExitOnFailure(hr, "Failed to set XML attribute"); + + hr = xmlRoot->appendChild(xmlElem, &tmpNode); + tmpNode.Release(); + ExitOnFailure(hr, "Failed to append XML element"); + +LExit: + return hr; +} + +HRESULT CRegistryXmlParser::Execute(WCHAR* pCustomActionData) +{ + HRESULT hr = S_OK; + CComPtr pXmlDoc; + CComPtr pNodes; + IXMLDOMNodeList* pTmpNodes = nullptr; + IXMLDOMNode* pTmpNode = nullptr; + IXMLDOMElement* pCurrElem = nullptr; + VARIANT_BOOL isXmlSuccess; + LONG nodeCount = 0; + DOMNodeType nodeType; + + // XML docs. + hr = ::CoCreateInstance(CLSID_DOMDocument, nullptr, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pXmlDoc); + ExitOnFailure(hr, "Failed to CoCreateInstance CLSID_DOMDocument"); + + hr = pXmlDoc->loadXML(pCustomActionData, &isXmlSuccess); + ExitOnFailure(hr, "Failed to load XML"); + if (!isXmlSuccess) + { + hr = E_FAIL; + ExitOnFailure(hr, "Failed to load XML"); + } + + hr = pXmlDoc->selectNodes(CComBSTR(L"/Root/*"), &pTmpNodes); + ExitOnFailure(hr, "Failed to select XML nodes"); + ExitOnNull(pTmpNodes, hr, E_FAIL, "Failed to select XML nodes"); + pNodes.Attach(pTmpNodes); + + hr = pNodes->get_length(&nodeCount); + ExitOnFailure(hr, "Failed to get node count"); + + for (LONG i = 0; i < nodeCount; ++i) + { + pTmpNode = nullptr; + + hr = pNodes->get_item(i, &pTmpNode); + ExitOnFailure(hr, "Failed to get node"); + ExitOnNull(pTmpNode, hr, E_FAIL, "Failed to get node"); + + hr = pTmpNode->get_nodeType(&nodeType); + ExitOnFailure(hr, "Failed to get node type"); + if (nodeType != DOMNodeType::NODE_ELEMENT) + { + hr = E_FAIL; + ExitOnFailure(hr, "Expected an element"); + } + + hr = pTmpNode->QueryInterface(IID_IXMLDOMElement, (void**)&pCurrElem); + ExitOnFailure(hr, "Failed quering as IID_IXMLDOMElement"); + ExitOnNull(pCurrElem, hr, E_FAIL, "Failed to get IID_IXMLDOMElement"); + + hr = XmlExecute(pCurrElem); + ExitOnFailure(hr, "Failed to parse-execute XML element"); + } + +LExit: + return hr; +} + +HRESULT CRegistryXmlParser::XmlExecute(IXMLDOMElement* xmlElem) +{ + HRESULT hr = S_OK; + CComBSTR tag; + CComVariant id, root, key, valName, valType, valData, area; + DWORD dwArea, dwRoot; + BYTE* pData = nullptr; + CRegDataSerializer regDataSer; + + // Get common fields. + hr = xmlElem->get_tagName(&tag); + ExitOnFailure(hr, "Failed to get XML tag name"); + hr = xmlElem->getAttribute(CComBSTR("Id"), &id); + ExitOnFailure(hr, "Failed to get XML Id attribute"); + hr = xmlElem->getAttribute(CComBSTR("Root"), &root); + ExitOnFailure(hr, "Failed to get XML Root attribute"); + hr = xmlElem->getAttribute(CComBSTR("Key"), &key); + ExitOnFailure(hr, "Failed to get XML Key attribute"); + hr = xmlElem->getAttribute(CComBSTR("Area"), &area); + ExitOnFailure(hr, "Failed to get XML Area attribute"); + + Bstr2Dword(root, (DWORD*)&dwRoot); + Bstr2Dword(area, (DWORD*)&dwArea); + + if (wcscmp(tag, L"DeleteKey") == 0) + { + hr = DeleteKey((CRegistryKey::RegRoot)dwRoot, key.bstrVal, (CRegistryKey::RegArea)dwArea); + ExitOnFailure(hr, "Failed to delete key '%ls', root '%i', area '%i'", key.bstrVal, dwRoot, dwArea); + ExitFunction(); + } + else if (wcscmp(tag, L"CreateKey") == 0) + { + hr = CreateKey((CRegistryKey::RegRoot)dwRoot, key.bstrVal, (CRegistryKey::RegArea)dwArea); + ExitOnFailure(hr, "Failed to create key"); + ExitFunction(); + } + else if (wcscmp(tag, L"DeleteValue") == 0) + { + hr = xmlElem->getAttribute(CComBSTR("Name"), &valName); + ExitOnFailure(hr, "Failed to get XML Name attribute"); + + hr = DeleteValue((CRegistryKey::RegRoot)dwRoot, key.bstrVal, (CRegistryKey::RegArea)dwArea, valName.bstrVal); + ExitOnFailure(hr, "Failed to create key"); + ExitFunction(); + } + else if (wcscmp(tag, L"CreateValue") == 0) + { + hr = xmlElem->getAttribute(CComBSTR("Name"), &valName); + ExitOnFailure(hr, "Failed to get XML Name attribute"); + hr = xmlElem->getAttribute(CComBSTR("Type"), &valType); + ExitOnFailure(hr, "Failed to get XML Type attribute"); + hr = xmlElem->getAttribute(CComBSTR("Data"), &valData); + ExitOnFailure(hr, "Failed to get XML Data attribute"); + + hr = regDataSer.DeSerialize(valData.bstrVal, valType.bstrVal); + ExitOnFailure(hr, "Failed to desrialize registry data"); + + hr = CreateValue( + (CRegistryKey::RegRoot)dwRoot + , key.bstrVal + , (CRegistryKey::RegArea)dwArea + , valName.bstrVal + , regDataSer.DataType() + , regDataSer.Data() + , regDataSer.Size()); + ExitOnFailure(hr, "Failed to create value"); + + ExitFunction(); + } + +LExit: + return hr; +} + +HRESULT CRegistryXmlParser::Bstr2Dword(VARIANT str, DWORD* dwVal) +{ + (*dwVal) = _wtol(str.bstrVal); + return S_OK; +} + +HRESULT CRegistryXmlParser::DeleteKey(CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area) +{ + CRegistryKey regKey; + HRESULT hr; + + hr = regKey.Open(root, subkeyName, (CRegistryKey::RegArea)area, CRegistryKey::RegAccess::All); + if (hr == E_FILENOTFOUND) + { + return S_OK; + } + ExitOnFailure(hr, "Failed to open registry key"); + + hr = regKey.Delete(); + ExitOnFailure(hr, "Failed to delete registry key"); + +LExit: + return hr; +} + +HRESULT CRegistryXmlParser::CreateKey(CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area) +{ + CRegistryKey regKey; + HRESULT hr; + + hr = regKey.Create(root, subkeyName, (CRegistryKey::RegArea)area, CRegistryKey::RegAccess::All); + ExitOnFailure(hr, "Failed to create registry key"); + +LExit: + return hr; +} + +HRESULT CRegistryXmlParser::DeleteValue(CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area, WCHAR* valName) +{ + CRegistryKey regKey; + HRESULT hr; + + hr = regKey.Open(root, subkeyName, (CRegistryKey::RegArea)area, CRegistryKey::RegAccess::All); + if (hr == E_FILENOTFOUND) + { + return S_OK; + } + ExitOnFailure(hr, "Failed to open registry key"); + + hr = regKey.DeleteValue(valName); + ExitOnFailure(hr, "Failed to open registry value"); + +LExit: + return hr; +} + +HRESULT CRegistryXmlParser::CreateValue(CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area, WCHAR* valName, DWORD valType, BYTE* valData, DWORD dataSize) +{ + CRegistryKey regKey; + HRESULT hr; + + hr = regKey.Create(root, subkeyName, (CRegistryKey::RegArea)area, CRegistryKey::RegAccess::All); + ExitOnFailure(hr, "Failed to create registry key"); + + hr = regKey.SetValue(valName, (CRegistryKey::RegValueType)valType, valData, dataSize); + ExitOnFailure(hr, "Failed to create registry value"); + +LExit: + return hr; +} diff --git a/PanelSwCustomActions/RegistryXmlParser.h b/src/PanelSwCustomActions/RegistryXmlParser.h old mode 100755 new mode 100644 similarity index 97% rename from PanelSwCustomActions/RegistryXmlParser.h rename to src/PanelSwCustomActions/RegistryXmlParser.h index 6d60b65c..5ddacb81 --- a/PanelSwCustomActions/RegistryXmlParser.h +++ b/src/PanelSwCustomActions/RegistryXmlParser.h @@ -1,41 +1,41 @@ -#pragma once - -#include "pch.h" -#include -#include -#include -#include -#include "../CaCommon/RegistryKey.h" - -class CRegistryXmlParser -{ -public: - - CRegistryXmlParser(); - ~CRegistryXmlParser(); - - HRESULT GetXmlString( BSTR* ppString); - - HRESULT Execute( WCHAR *pCustomActionData); - - HRESULT AddDeleteKey( WCHAR* pId, CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area); - HRESULT AddDeleteValue( WCHAR* pId, CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area, WCHAR* valName); - - HRESULT AddCreateKey( WCHAR* pId, CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area); - HRESULT AddCreateValue(WCHAR* pId, CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area, WCHAR* valName, CRegistryKey::RegValueType valType, WCHAR* pData); - -private: - - HRESULT XmlExecute( IXMLDOMElement *xmlElem); - - HRESULT Bstr2Dword( VARIANT str, DWORD* dwVal); - - HRESULT DeleteKey( CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area); - HRESULT CreateKey( CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area); - - HRESULT DeleteValue( CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area, WCHAR* valName); - HRESULT CreateValue( CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area, WCHAR* valName, DWORD valType, BYTE* valData, DWORD dataSize); - - CComPtr _pXmlDoc; -}; - +#pragma once + +#include "pch.h" +#include +#include +#include +#include +#include "../CaCommon/RegistryKey.h" + +class CRegistryXmlParser +{ +public: + + CRegistryXmlParser(); + ~CRegistryXmlParser(); + + HRESULT GetXmlString( BSTR* ppString); + + HRESULT Execute( WCHAR *pCustomActionData); + + HRESULT AddDeleteKey( WCHAR* pId, CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area); + HRESULT AddDeleteValue( WCHAR* pId, CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area, WCHAR* valName); + + HRESULT AddCreateKey( WCHAR* pId, CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area); + HRESULT AddCreateValue(WCHAR* pId, CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area, WCHAR* valName, CRegistryKey::RegValueType valType, WCHAR* pData); + +private: + + HRESULT XmlExecute( IXMLDOMElement *xmlElem); + + HRESULT Bstr2Dword( VARIANT str, DWORD* dwVal); + + HRESULT DeleteKey( CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area); + HRESULT CreateKey( CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area); + + HRESULT DeleteValue( CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area, WCHAR* valName); + HRESULT CreateValue( CRegistryKey::RegRoot root, WCHAR* subkeyName, CRegistryKey::RegArea area, WCHAR* valName, DWORD valType, BYTE* valData, DWORD dataSize); + + CComPtr _pXmlDoc; +}; + diff --git a/PanelSwCustomActions/RegularExpression.cpp b/src/PanelSwCustomActions/RegularExpression.cpp similarity index 97% rename from PanelSwCustomActions/RegularExpression.cpp rename to src/PanelSwCustomActions/RegularExpression.cpp index c8ff9d09..708b4139 100644 --- a/PanelSwCustomActions/RegularExpression.cpp +++ b/src/PanelSwCustomActions/RegularExpression.cpp @@ -1,348 +1,348 @@ -#include "pch.h" -#include -#include "FileOperations.h" -#include "fileRegexDetails.pb.h" - -using namespace std; -using namespace ::com::panelsw::ca; -#define RegularExpressionQuery L"SELECT `Id`, `FilePath`, `Input`, `Expression`, `Replacement`, `DstProperty_`, `Flags`, `Condition` FROM `PSW_RegularExpression` ORDER BY `Order`" -enum eRegularExpressionQuery { Id = 1, FilePath, Input, Expression, Replacement, DstProperty, Flags, Condition }; -enum SearchFlags -{ - Search = 0 - , Replace = 1 -}; - -enum ResultFlags -{ - MustMatch = 1 -}; - -enum MatchFlags -{ - IgnoreCare = 1 - , Extended = 2 -}; - -union RegexFlags -{ - unsigned int u; - struct - { - SearchFlags search : 1; - ResultFlags result : 1; - MatchFlags match : 2; - unsigned dontCare : 4; - } s; -}; - -static HRESULT SearchUnicode(LPCWSTR szProperty, LPCWSTR szExpression, LPCWSTR szInput, RegexFlags flags, std::regex_constants::syntax_option_type syntax); -static HRESULT SearchMultibyte(LPCWSTR szProperty, LPCWSTR szExpression, LPCSTR szInput, RegexFlags flags, std::regex_constants::syntax_option_type syntax); -static HRESULT SearchInFile(LPCWSTR szProperty, LPCWSTR szExpression, LPCWSTR szFilePath, RegexFlags flags, std::regex_constants::syntax_option_type syntax); - -extern "C" UINT __stdcall RegularExpression(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - PMSIHANDLE hView; - PMSIHANDLE hRecord; - bool bIgnoreErrors = false; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - // Ensure table PSW_XmlSearch exists. - hr = WcaTableExists(L"PSW_RegularExpression"); - ExitOnFailure(hr, "Failed to check if table exists 'PSW_RegularExpression'"); - ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_RegularExpression'. Have you authored 'PanelSw:RegularExpression' entries in WiX code?"); - - // Execute view - hr = WcaOpenExecuteView(RegularExpressionQuery, &hView); - ExitOnFailure(hr, "Failed to execute SQL query on 'PSW_RegularExpression'."); - - // Iterate records - while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) - { - ExitOnFailure(hr, "Failed to fetch record."); - - // Get fields - CWixString szExpressionFormat, szExpression; - CWixString sId, sFilePath, sInput, sReplace, sDstProperty, sCondition; - int iFlags = 0; - RegexFlags flags; - std::regex_constants::syntax_option_type syntax = (std::regex_constants::syntax_option_type)0; - - hr = WcaGetRecordString(hRecord, eRegularExpressionQuery::Id, (LPWSTR*)sId); - ExitOnFailure(hr, "Failed to get Id."); - hr = WcaGetRecordFormattedString(hRecord, eRegularExpressionQuery::FilePath, (LPWSTR*)sFilePath); - ExitOnFailure(hr, "Failed to get FilePath."); - hr = WcaGetRecordFormattedString(hRecord, eRegularExpressionQuery::Input, (LPWSTR*)sInput); - ExitOnFailure(hr, "Failed to get Input."); - hr = WcaGetRecordString(hRecord, eRegularExpressionQuery::Expression, (LPWSTR*)szExpressionFormat); - ExitOnFailure(hr, "Failed to get Expression."); - hr = WcaGetRecordFormattedString(hRecord, eRegularExpressionQuery::Replacement, (LPWSTR*)sReplace); - ExitOnFailure(hr, "Failed to get Replacement."); - hr = WcaGetRecordFormattedString(hRecord, eRegularExpressionQuery::DstProperty, (LPWSTR*)sDstProperty); - ExitOnFailure(hr, "Failed to get DstProperty_."); - hr = WcaGetRecordInteger(hRecord, eRegularExpressionQuery::Flags, &iFlags); - ExitOnFailure(hr, "Failed to get Flags."); - flags.u = *reinterpret_cast(&iFlags); - hr = WcaGetRecordString(hRecord, eRegularExpressionQuery::Condition, (LPWSTR*)sCondition); - ExitOnFailure(hr, "Failed to get Condition."); - - hr = szExpression.MsiFormat((LPCWSTR)szExpressionFormat); - ExitOnFailure(hr, "Failed to format Expression."); - - // Test condition - if (!sCondition.IsNullOrEmpty()) - { - MSICONDITION condRes = ::MsiEvaluateConditionW(hInstall, (LPCWSTR)sCondition); - switch (condRes) - { - case MSICONDITION::MSICONDITION_NONE: - case MSICONDITION::MSICONDITION_TRUE: - - WcaLog(LOGMSG_STANDARD, "Condition evaluated to true / none for %ls", (LPCWSTR)sId); - break; - - case MSICONDITION::MSICONDITION_FALSE: - - WcaLog(LOGMSG_STANDARD, "Skipping. Condition evaluated to false for %ls", (LPCWSTR)sId); - continue; - - case MSICONDITION::MSICONDITION_ERROR: - - hr = E_FAIL; - ExitOnFailure(hr, "Bad Condition field"); - } - } - CDeferredActionBase::LogUnformatted(LOGLEVEL::LOGMSG_STANDARD, false, L"Executing regular expression query '%ls'", szExpression.Obfuscated()); - - // Syntax flags - if (flags.s.match & MatchFlags::IgnoreCare) - { - syntax |= std::regex_constants::syntax_option_type::icase; - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Ignoring case", (LPCWSTR)sId); - } - if (flags.s.match & MatchFlags::Extended) - { - syntax |= std::regex_constants::syntax_option_type::extended; - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Extended regex syntax", (LPCWSTR)sId); - } - - // Match in file - if (!sFilePath.IsNullOrEmpty()) - { - hr = SearchInFile(sDstProperty, szExpression, sFilePath, flags, syntax); - ExitOnFailure(hr, "Failed executing search"); - } - // Match in property - else if (flags.s.search == SearchFlags::Search) - { - hr = SearchUnicode(sDstProperty, szExpression, sInput, flags, syntax); - ExitOnFailure(hr, "Failed executing search"); - } - // Replace - else - { - try - { - wregex rx((LPCWSTR)szExpression, syntax); - std::wstring rep = regex_replace((LPCWSTR)sInput, rx, (LPCWSTR)sReplace); - - hr = WcaSetProperty(sDstProperty, rep.c_str()); - ExitOnFailure(hr, "Failed setting target property"); - } - catch (std::regex_error ex) - { - hr = HRESULT_FROM_WIN32(ex.code()); - if (SUCCEEDED(hr)) - { - hr = E_FAIL; - } - ExitOnFailure(hr, "Failed evaluating regular expression. %hs", ex.what()); - } - } - } - - hr = ERROR_SUCCESS; - -LExit: - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - -static HRESULT SearchUnicode(LPCWSTR szProperty, LPCWSTR szExpression, LPCWSTR szInput, RegexFlags flags, std::regex_constants::syntax_option_type syntax) -{ - HRESULT hr = S_OK; - bool bRes = true; - match_results results; - CWixString sPropName; - - try - { - wregex rx(szExpression, syntax); - bRes = regex_search(szInput, results, rx); - ExitOnNull((bRes || ((flags.s.result & ResultFlags::MustMatch) == 0)), hr, E_FAIL, "Regex returned no matches"); - } - catch (std::regex_error ex) - { - hr = HRESULT_FROM_WIN32(ex.code()); - if (SUCCEEDED(hr)) - { - hr = E_FAIL; - } - ExitOnFailure(hr, "Failed evaluating regular expression. %hs", ex.what()); - } - - if (!bRes) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No matches"); - ExitFunction1(hr = S_FALSE); - } - - hr = sPropName.Format(L"%ls_COUNT", szProperty); - ExitOnFailure(hr, "Failed formatting string"); - - hr = WcaSetIntProperty(szProperty, results.size()); - ExitOnFailure(hr, "Failed setting property '%ls'", szProperty); - - hr = WcaSetIntProperty((LPCWSTR)sPropName, results.size()); - ExitOnFailure(hr, "Failed setting property '%ls'", (LPCWSTR)sPropName); - - // Iterate results - for (size_t i = 0; i < results.size(); ++i) - { - const std::sub_match& match = results[i]; - - hr = sPropName.Format(L"%ls_%Iu", szProperty, i); - ExitOnFailure(hr, "Failed formatting string"); - - hr = WcaSetProperty((LPCWSTR)sPropName, match.str().c_str()); - ExitOnFailure(hr, "Failed setting property '%ls'", (LPCWSTR)sPropName); - } - -LExit: - return hr; -} - -static HRESULT SearchMultibyte(LPCWSTR szProperty, LPCWSTR szExpression, LPCSTR szInput, RegexFlags flags, std::regex_constants::syntax_option_type syntax) -{ - HRESULT hr = S_OK; - LPSTR szPropertyA = nullptr; - LPSTR szExpressionA = nullptr; - match_results results; - bool bRes = true; - CWixString szCntProp; - - hr = StrAnsiAllocString(&szExpressionA, szExpression, 0, CP_UTF8); - ExitOnFailure(hr, "Failed converting string to multibyte"); - - // New scope to construct regex in - try - { - regex rx(szExpressionA, syntax); - - bRes = regex_search(szInput, results, rx); - ExitOnNull((bRes || ((flags.s.result & ResultFlags::MustMatch) == 0)), hr, E_FAIL, "Regex returned no matches"); - } - catch (std::regex_error ex) - { - hr = HRESULT_FROM_WIN32(ex.code()); - if (SUCCEEDED(hr)) - { - hr = E_FAIL; - } - ExitOnFailure(hr, "Failed evaluating regular expression. %hs", ex.what()); - } - - if (!bRes) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No matches"); - ExitFunction1(hr = S_FALSE); - } - - hr = szCntProp.Format(L"%ls_COUNT", szProperty); - ExitOnFailure(hr, "Failed formatting string"); - - hr = WcaSetIntProperty(szProperty, results.size()); - ExitOnFailure(hr, "Failed setting property '%ls'", szProperty); - - hr = ::WcaSetIntProperty(szCntProp, results.size()); - ExitOnFailure(hr, "Failed setting property '%ls'", (LPCWSTR)szCntProp); - - // Iterate results - for (size_t i = 0; i < results.size(); ++i) - { - const std::sub_match& match = results[i]; - - hr = StrAnsiAllocFormatted(&szPropertyA, "%ls_%Iu", szProperty, i); - ExitOnFailure(hr, "Failed formatting ansi string"); - - hr = ::MsiSetPropertyA(WcaGetInstallHandle(), szPropertyA, match.str().c_str()); - ExitOnFailure(hr, "Failed setting property '%hs'", szPropertyA); - - ReleaseNullMem(szPropertyA); - } - -LExit: - ReleaseMem(szExpressionA); - ReleaseMem(szPropertyA); - return hr; -} - - -static HRESULT SearchInFile(LPCWSTR szProperty, LPCWSTR szExpression, LPCWSTR szFilePath, RegexFlags flags, std::regex_constants::syntax_option_type syntax) -{ - HRESULT hr = S_OK; - bool bRes = true; - FileRegexDetails::FileEncoding eDetectedEncoding = FileRegexDetails::FileEncoding::FileRegexDetails_FileEncoding_None; - HANDLE hFile = INVALID_HANDLE_VALUE; - void* pFileContents = nullptr; - DWORD dwFileSize = 0; - DWORD dwBytesRead = 0; - - if (flags.s.search == SearchFlags::Replace) - { - hr = E_INVALIDARG; - ExitOnFailure(hr, "Can't perform Regex replace in immediate custom action. Use FileRegex for that"); - } - - hFile = ::CreateFile(szFilePath, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - ExitOnNullWithLastError((hFile != INVALID_HANDLE_VALUE), hr, "Failed opening file"); - - dwFileSize = ::GetFileSize(hFile, nullptr); - pFileContents = MemAlloc(dwFileSize + 2, FALSE); - ExitOnNull(pFileContents, hr, E_FAIL, "Failed allocating memory"); - - // Terminate with ascii/wchar NULL. - ((BYTE*)pFileContents)[dwFileSize] = NULL; - ((BYTE*)pFileContents)[dwFileSize + 1] = NULL; - - bRes = ::ReadFile(hFile, pFileContents, dwFileSize, &dwBytesRead, nullptr); - ExitOnNullWithLastError(bRes, hr, "Failed reading file"); - ExitOnNull((dwFileSize == dwBytesRead), hr, E_FAIL, "Failed reading file. Read %i/%i bytes", dwBytesRead, dwFileSize); - - eDetectedEncoding = CFileOperations::DetectEncoding(pFileContents, dwFileSize); - if (eDetectedEncoding == FileRegexDetails::FileEncoding::FileRegexDetails_FileEncoding_MultiByte) - { - hr = SearchMultibyte(szProperty, szExpression, (LPCSTR)pFileContents, flags, syntax); - ExitOnFailure(hr, "Failed executing multibyte regular expression"); - } - else - { - hr = SearchUnicode(szProperty, szExpression, (LPCWSTR)pFileContents, flags, syntax); - ExitOnFailure(hr, "Failed executing unicode regular expression"); - } - -LExit: - if (hFile != INVALID_HANDLE_VALUE) - { - ::CloseHandle(hFile); - } - ReleaseMem(pFileContents); - - return hr; -} +#include "pch.h" +#include +#include "FileOperations.h" +#include "fileRegexDetails.pb.h" + +using namespace std; +using namespace ::com::panelsw::ca; +#define RegularExpressionQuery L"SELECT `Id`, `FilePath`, `Input`, `Expression`, `Replacement`, `DstProperty_`, `Flags`, `Condition` FROM `PSW_RegularExpression` ORDER BY `Order`" +enum eRegularExpressionQuery { Id = 1, FilePath, Input, Expression, Replacement, DstProperty, Flags, Condition }; +enum SearchFlags +{ + Search = 0 + , Replace = 1 +}; + +enum ResultFlags +{ + MustMatch = 1 +}; + +enum MatchFlags +{ + IgnoreCare = 1 + , Extended = 2 +}; + +union RegexFlags +{ + unsigned int u; + struct + { + SearchFlags search : 1; + ResultFlags result : 1; + MatchFlags match : 2; + unsigned dontCare : 4; + } s; +}; + +static HRESULT SearchUnicode(LPCWSTR szProperty, LPCWSTR szExpression, LPCWSTR szInput, RegexFlags flags, std::regex_constants::syntax_option_type syntax); +static HRESULT SearchMultibyte(LPCWSTR szProperty, LPCWSTR szExpression, LPCSTR szInput, RegexFlags flags, std::regex_constants::syntax_option_type syntax); +static HRESULT SearchInFile(LPCWSTR szProperty, LPCWSTR szExpression, LPCWSTR szFilePath, RegexFlags flags, std::regex_constants::syntax_option_type syntax); + +extern "C" UINT __stdcall RegularExpression(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + PMSIHANDLE hView; + PMSIHANDLE hRecord; + bool bIgnoreErrors = false; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + // Ensure table PSW_XmlSearch exists. + hr = WcaTableExists(L"PSW_RegularExpression"); + ExitOnFailure(hr, "Failed to check if table exists 'PSW_RegularExpression'"); + ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_RegularExpression'. Have you authored 'PanelSw:RegularExpression' entries in WiX code?"); + + // Execute view + hr = WcaOpenExecuteView(RegularExpressionQuery, &hView); + ExitOnFailure(hr, "Failed to execute SQL query on 'PSW_RegularExpression'."); + + // Iterate records + while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) + { + ExitOnFailure(hr, "Failed to fetch record."); + + // Get fields + CWixString szExpressionFormat, szExpression; + CWixString sId, sFilePath, sInput, sReplace, sDstProperty, sCondition; + int iFlags = 0; + RegexFlags flags; + std::regex_constants::syntax_option_type syntax = (std::regex_constants::syntax_option_type)0; + + hr = WcaGetRecordString(hRecord, eRegularExpressionQuery::Id, (LPWSTR*)sId); + ExitOnFailure(hr, "Failed to get Id."); + hr = WcaGetRecordFormattedString(hRecord, eRegularExpressionQuery::FilePath, (LPWSTR*)sFilePath); + ExitOnFailure(hr, "Failed to get FilePath."); + hr = WcaGetRecordFormattedString(hRecord, eRegularExpressionQuery::Input, (LPWSTR*)sInput); + ExitOnFailure(hr, "Failed to get Input."); + hr = WcaGetRecordString(hRecord, eRegularExpressionQuery::Expression, (LPWSTR*)szExpressionFormat); + ExitOnFailure(hr, "Failed to get Expression."); + hr = WcaGetRecordFormattedString(hRecord, eRegularExpressionQuery::Replacement, (LPWSTR*)sReplace); + ExitOnFailure(hr, "Failed to get Replacement."); + hr = WcaGetRecordFormattedString(hRecord, eRegularExpressionQuery::DstProperty, (LPWSTR*)sDstProperty); + ExitOnFailure(hr, "Failed to get DstProperty_."); + hr = WcaGetRecordInteger(hRecord, eRegularExpressionQuery::Flags, &iFlags); + ExitOnFailure(hr, "Failed to get Flags."); + flags.u = *reinterpret_cast(&iFlags); + hr = WcaGetRecordString(hRecord, eRegularExpressionQuery::Condition, (LPWSTR*)sCondition); + ExitOnFailure(hr, "Failed to get Condition."); + + hr = szExpression.MsiFormat((LPCWSTR)szExpressionFormat); + ExitOnFailure(hr, "Failed to format Expression."); + + // Test condition + if (!sCondition.IsNullOrEmpty()) + { + MSICONDITION condRes = ::MsiEvaluateConditionW(hInstall, (LPCWSTR)sCondition); + switch (condRes) + { + case MSICONDITION::MSICONDITION_NONE: + case MSICONDITION::MSICONDITION_TRUE: + + WcaLog(LOGMSG_STANDARD, "Condition evaluated to true / none for %ls", (LPCWSTR)sId); + break; + + case MSICONDITION::MSICONDITION_FALSE: + + WcaLog(LOGMSG_STANDARD, "Skipping. Condition evaluated to false for %ls", (LPCWSTR)sId); + continue; + + case MSICONDITION::MSICONDITION_ERROR: + + hr = E_FAIL; + ExitOnFailure(hr, "Bad Condition field"); + } + } + CDeferredActionBase::LogUnformatted(LOGLEVEL::LOGMSG_STANDARD, false, L"Executing regular expression query '%ls'", szExpression.Obfuscated()); + + // Syntax flags + if (flags.s.match & MatchFlags::IgnoreCare) + { + syntax |= std::regex_constants::syntax_option_type::icase; + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Ignoring case", (LPCWSTR)sId); + } + if (flags.s.match & MatchFlags::Extended) + { + syntax |= std::regex_constants::syntax_option_type::extended; + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Extended regex syntax", (LPCWSTR)sId); + } + + // Match in file + if (!sFilePath.IsNullOrEmpty()) + { + hr = SearchInFile(sDstProperty, szExpression, sFilePath, flags, syntax); + ExitOnFailure(hr, "Failed executing search"); + } + // Match in property + else if (flags.s.search == SearchFlags::Search) + { + hr = SearchUnicode(sDstProperty, szExpression, sInput, flags, syntax); + ExitOnFailure(hr, "Failed executing search"); + } + // Replace + else + { + try + { + wregex rx((LPCWSTR)szExpression, syntax); + std::wstring rep = regex_replace((LPCWSTR)sInput, rx, (LPCWSTR)sReplace); + + hr = WcaSetProperty(sDstProperty, rep.c_str()); + ExitOnFailure(hr, "Failed setting target property"); + } + catch (std::regex_error ex) + { + hr = HRESULT_FROM_WIN32(ex.code()); + if (SUCCEEDED(hr)) + { + hr = E_FAIL; + } + ExitOnFailure(hr, "Failed evaluating regular expression. %hs", ex.what()); + } + } + } + + hr = ERROR_SUCCESS; + +LExit: + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +static HRESULT SearchUnicode(LPCWSTR szProperty, LPCWSTR szExpression, LPCWSTR szInput, RegexFlags flags, std::regex_constants::syntax_option_type syntax) +{ + HRESULT hr = S_OK; + bool bRes = true; + match_results results; + CWixString sPropName; + + try + { + wregex rx(szExpression, syntax); + bRes = regex_search(szInput, results, rx); + ExitOnNull((bRes || ((flags.s.result & ResultFlags::MustMatch) == 0)), hr, E_FAIL, "Regex returned no matches"); + } + catch (std::regex_error ex) + { + hr = HRESULT_FROM_WIN32(ex.code()); + if (SUCCEEDED(hr)) + { + hr = E_FAIL; + } + ExitOnFailure(hr, "Failed evaluating regular expression. %hs", ex.what()); + } + + if (!bRes) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No matches"); + ExitFunction1(hr = S_FALSE); + } + + hr = sPropName.Format(L"%ls_COUNT", szProperty); + ExitOnFailure(hr, "Failed formatting string"); + + hr = WcaSetIntProperty(szProperty, results.size()); + ExitOnFailure(hr, "Failed setting property '%ls'", szProperty); + + hr = WcaSetIntProperty((LPCWSTR)sPropName, results.size()); + ExitOnFailure(hr, "Failed setting property '%ls'", (LPCWSTR)sPropName); + + // Iterate results + for (size_t i = 0; i < results.size(); ++i) + { + const std::sub_match& match = results[i]; + + hr = sPropName.Format(L"%ls_%Iu", szProperty, i); + ExitOnFailure(hr, "Failed formatting string"); + + hr = WcaSetProperty((LPCWSTR)sPropName, match.str().c_str()); + ExitOnFailure(hr, "Failed setting property '%ls'", (LPCWSTR)sPropName); + } + +LExit: + return hr; +} + +static HRESULT SearchMultibyte(LPCWSTR szProperty, LPCWSTR szExpression, LPCSTR szInput, RegexFlags flags, std::regex_constants::syntax_option_type syntax) +{ + HRESULT hr = S_OK; + LPSTR szPropertyA = nullptr; + LPSTR szExpressionA = nullptr; + match_results results; + bool bRes = true; + CWixString szCntProp; + + hr = StrAnsiAllocString(&szExpressionA, szExpression, 0, CP_UTF8); + ExitOnFailure(hr, "Failed converting string to multibyte"); + + // New scope to construct regex in + try + { + regex rx(szExpressionA, syntax); + + bRes = regex_search(szInput, results, rx); + ExitOnNull((bRes || ((flags.s.result & ResultFlags::MustMatch) == 0)), hr, E_FAIL, "Regex returned no matches"); + } + catch (std::regex_error ex) + { + hr = HRESULT_FROM_WIN32(ex.code()); + if (SUCCEEDED(hr)) + { + hr = E_FAIL; + } + ExitOnFailure(hr, "Failed evaluating regular expression. %hs", ex.what()); + } + + if (!bRes) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No matches"); + ExitFunction1(hr = S_FALSE); + } + + hr = szCntProp.Format(L"%ls_COUNT", szProperty); + ExitOnFailure(hr, "Failed formatting string"); + + hr = WcaSetIntProperty(szProperty, results.size()); + ExitOnFailure(hr, "Failed setting property '%ls'", szProperty); + + hr = ::WcaSetIntProperty(szCntProp, results.size()); + ExitOnFailure(hr, "Failed setting property '%ls'", (LPCWSTR)szCntProp); + + // Iterate results + for (size_t i = 0; i < results.size(); ++i) + { + const std::sub_match& match = results[i]; + + hr = StrAnsiAllocFormatted(&szPropertyA, "%ls_%Iu", szProperty, i); + ExitOnFailure(hr, "Failed formatting ansi string"); + + hr = ::MsiSetPropertyA(WcaGetInstallHandle(), szPropertyA, match.str().c_str()); + ExitOnFailure(hr, "Failed setting property '%hs'", szPropertyA); + + ReleaseNullMem(szPropertyA); + } + +LExit: + ReleaseMem(szExpressionA); + ReleaseMem(szPropertyA); + return hr; +} + + +static HRESULT SearchInFile(LPCWSTR szProperty, LPCWSTR szExpression, LPCWSTR szFilePath, RegexFlags flags, std::regex_constants::syntax_option_type syntax) +{ + HRESULT hr = S_OK; + bool bRes = true; + FileRegexDetails::FileEncoding eDetectedEncoding = FileRegexDetails::FileEncoding::FileRegexDetails_FileEncoding_None; + HANDLE hFile = INVALID_HANDLE_VALUE; + void* pFileContents = nullptr; + DWORD dwFileSize = 0; + DWORD dwBytesRead = 0; + + if (flags.s.search == SearchFlags::Replace) + { + hr = E_INVALIDARG; + ExitOnFailure(hr, "Can't perform Regex replace in immediate custom action. Use FileRegex for that"); + } + + hFile = ::CreateFile(szFilePath, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + ExitOnNullWithLastError((hFile != INVALID_HANDLE_VALUE), hr, "Failed opening file"); + + dwFileSize = ::GetFileSize(hFile, nullptr); + pFileContents = MemAlloc(dwFileSize + 2, FALSE); + ExitOnNull(pFileContents, hr, E_FAIL, "Failed allocating memory"); + + // Terminate with ascii/wchar NULL. + ((BYTE*)pFileContents)[dwFileSize] = NULL; + ((BYTE*)pFileContents)[dwFileSize + 1] = NULL; + + bRes = ::ReadFile(hFile, pFileContents, dwFileSize, &dwBytesRead, nullptr); + ExitOnNullWithLastError(bRes, hr, "Failed reading file"); + ExitOnNull((dwFileSize == dwBytesRead), hr, E_FAIL, "Failed reading file. Read %i/%i bytes", dwBytesRead, dwFileSize); + + eDetectedEncoding = CFileOperations::DetectEncoding(pFileContents, dwFileSize); + if (eDetectedEncoding == FileRegexDetails::FileEncoding::FileRegexDetails_FileEncoding_MultiByte) + { + hr = SearchMultibyte(szProperty, szExpression, (LPCSTR)pFileContents, flags, syntax); + ExitOnFailure(hr, "Failed executing multibyte regular expression"); + } + else + { + hr = SearchUnicode(szProperty, szExpression, (LPCWSTR)pFileContents, flags, syntax); + ExitOnFailure(hr, "Failed executing unicode regular expression"); + } + +LExit: + if (hFile != INVALID_HANDLE_VALUE) + { + ::CloseHandle(hFile); + } + ReleaseMem(pFileContents); + + return hr; +} diff --git a/PanelSwCustomActions/RemoveRegistryValue.cpp b/src/PanelSwCustomActions/RemoveRegistryValue.cpp similarity index 97% rename from PanelSwCustomActions/RemoveRegistryValue.cpp rename to src/PanelSwCustomActions/RemoveRegistryValue.cpp index 028c3721..4d683d87 100644 --- a/PanelSwCustomActions/RemoveRegistryValue.cpp +++ b/src/PanelSwCustomActions/RemoveRegistryValue.cpp @@ -1,159 +1,159 @@ -#include "pch.h" -#include "../CaCommon/RegistryKey.h" -#include "RegistryXmlParser.h" -#include "RegDataSerializer.h" - -#define RemoveRegistryValueQuery L"SELECT `Id`, `Root`, `Key`, `Name`, `Area`, `Attributes`, `Condition` FROM `PSW_RemoveRegistryValue`" -enum eRemoveRegistryValueQuery { Id = 1, Root, Key, Name, Area, Attributes, Condition }; - -extern "C" UINT __stdcall RemoveRegistryValue_Immediate(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - CRegistryXmlParser actionData; - CRegistryXmlParser rollbackActionData; - PMSIHANDLE hView; - PMSIHANDLE hRec; - CComBSTR xmlString; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - // Ensure table PSW_RemoveRegistryValue exists. - hr = WcaTableExists(L"PSW_RemoveRegistryValue"); - ExitOnFailure(hr, "Failed to check if table exists 'PSW_RemoveRegistryValue'"); - ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_RemoveRegistryValue'. Have you authored 'PanelSw:RemoveRegistryValue' entries in WiX code?"); - - hr = WcaOpenExecuteView(RemoveRegistryValueQuery, &hView); - ExitOnFailure(hr, "Failed to execute view"); - - while (E_NOMOREITEMS != (hr = WcaFetchRecord(hView, &hRec))) - { - ExitOnFailure(hr, "Failed to fetch record"); - - // Get record. - LPWSTR pId = nullptr; - LPWSTR pName = nullptr; - LPWSTR pRoot = nullptr; - LPWSTR pKey = nullptr; - LPWSTR pArea = nullptr; - CRegistryKey::RegRoot eRoot; - CRegistryKey::RegArea eArea; - CRegistryKey key; - LPWSTR pCondition = nullptr; - - // existing value details - BYTE* pData = nullptr; - LPWSTR pDataString = nullptr; - CRegistryKey::RegValueType valueType; - DWORD dwValueSize = 0; - CRegDataSerializer dataSerialiser; - - hr = WcaGetRecordString(hRec, eRemoveRegistryValueQuery::Id, &pId); - ExitOnFailure(hr, "Failed to get Id"); - hr = WcaGetRecordString(hRec, eRemoveRegistryValueQuery::Root, &pRoot); - ExitOnFailure(hr, "Failed to get Root"); - hr = WcaGetRecordFormattedString(hRec, eRemoveRegistryValueQuery::Key, &pKey); - ExitOnFailure(hr, "Failed to get Key"); - hr = WcaGetRecordFormattedString(hRec, eRemoveRegistryValueQuery::Name, &pName); - ExitOnFailure(hr, "Failed to get Name"); - hr = WcaGetRecordString(hRec, eRemoveRegistryValueQuery::Area, &pArea); - ExitOnFailure(hr, "Failed to get Area"); - hr = WcaGetRecordString(hRec, eRemoveRegistryValueQuery::Condition, &pCondition); - ExitOnFailure(hr, "Failed to get Condition"); - - MSICONDITION cond = ::MsiEvaluateCondition(hInstall, pCondition); - switch (cond) - { - case MSICONDITION::MSICONDITION_NONE: - case MSICONDITION::MSICONDITION_TRUE: - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Condition evaluated true/none for %ls", pId); - break; - - case MSICONDITION::MSICONDITION_FALSE: - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Condition evaluated false for %ls", pId); - continue; - - case MSICONDITION::MSICONDITION_ERROR: - hr = E_FAIL; - ExitOnFailure(hr, "Failed to evaluate condition"); - } - - // Parse root name. - hr = CRegistryKey::ParseRoot(pRoot, &eRoot); - ExitOnFailure(hr, "Failed to parse root"); - - // Parse area name. - hr = CRegistryKey::ParseArea(pArea, &eArea); - ExitOnFailure(hr, "Failed to parse area"); - - // CustomActionData - hr = actionData.AddDeleteValue(pId, eRoot, pKey, eArea, pName); - ExitOnFailure(hr, "Failed to add 'DeleteValue' to CustomActionData"); - - // Rollback CustomActionData - hr = key.Open(eRoot, pKey, eArea, CRegistryKey::RegAccess::ReadOnly); - if (hr == E_FILENOTFOUND) - { - hr = S_OK; - continue; - } - ExitOnFailure(hr, "Failed to query existing key"); - - hr = key.GetValue(pName, &pData, &valueType, &dwValueSize); - if (hr == E_FILENOTFOUND) - { - hr = S_OK; - continue; - } - ExitOnFailure(hr, "Failed to query existing value"); - - hr = dataSerialiser.Set(pData, valueType, dwValueSize); - ExitOnFailure(hr, "Failed to initialize data serializer"); - - hr = dataSerialiser.Serialize(&pDataString); - ExitOnFailure(hr, "Failed to serialize data"); - - hr = rollbackActionData.AddCreateValue(pId, eRoot, pKey, eArea, pName, valueType, pDataString); - ExitOnFailure(hr, "Failed to create XML element"); - } - - hr = rollbackActionData.GetXmlString(&xmlString); - ExitOnFailure(hr, "Failed to read XML as text"); - hr = WcaDoDeferredAction(L"RemoveRegistryValue_rollback", xmlString, 0); - ExitOnFailure(hr, "Failed to set property"); - xmlString.Empty(); - - hr = actionData.GetXmlString(&xmlString); - ExitOnFailure(hr, "Failed to read XML as text"); - hr = WcaDoDeferredAction(L"RemoveRegistryValue_deferred", xmlString, 0); - ExitOnFailure(hr, "Failed to set property"); - xmlString.Empty(); - -LExit: - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - -extern "C" UINT __stdcall RemoveRegistryValue_Deferred(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - CRegistryXmlParser action; - LPWSTR pActionData = nullptr; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - hr = WcaGetProperty(L"CustomActionData", &pActionData); - ExitOnFailure(hr, "Failed to get CustomActionData"); - - hr = action.Execute(pActionData); - ExitOnFailure(hr, "Failed to parse-execute RemoveRegistryValue"); - -LExit: - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} +#include "pch.h" +#include "../CaCommon/RegistryKey.h" +#include "RegistryXmlParser.h" +#include "RegDataSerializer.h" + +#define RemoveRegistryValueQuery L"SELECT `Id`, `Root`, `Key`, `Name`, `Area`, `Attributes`, `Condition` FROM `PSW_RemoveRegistryValue`" +enum eRemoveRegistryValueQuery { Id = 1, Root, Key, Name, Area, Attributes, Condition }; + +extern "C" UINT __stdcall RemoveRegistryValue_Immediate(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + CRegistryXmlParser actionData; + CRegistryXmlParser rollbackActionData; + PMSIHANDLE hView; + PMSIHANDLE hRec; + CComBSTR xmlString; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + // Ensure table PSW_RemoveRegistryValue exists. + hr = WcaTableExists(L"PSW_RemoveRegistryValue"); + ExitOnFailure(hr, "Failed to check if table exists 'PSW_RemoveRegistryValue'"); + ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_RemoveRegistryValue'. Have you authored 'PanelSw:RemoveRegistryValue' entries in WiX code?"); + + hr = WcaOpenExecuteView(RemoveRegistryValueQuery, &hView); + ExitOnFailure(hr, "Failed to execute view"); + + while (E_NOMOREITEMS != (hr = WcaFetchRecord(hView, &hRec))) + { + ExitOnFailure(hr, "Failed to fetch record"); + + // Get record. + LPWSTR pId = nullptr; + LPWSTR pName = nullptr; + LPWSTR pRoot = nullptr; + LPWSTR pKey = nullptr; + LPWSTR pArea = nullptr; + CRegistryKey::RegRoot eRoot; + CRegistryKey::RegArea eArea; + CRegistryKey key; + LPWSTR pCondition = nullptr; + + // existing value details + BYTE* pData = nullptr; + LPWSTR pDataString = nullptr; + CRegistryKey::RegValueType valueType; + DWORD dwValueSize = 0; + CRegDataSerializer dataSerialiser; + + hr = WcaGetRecordString(hRec, eRemoveRegistryValueQuery::Id, &pId); + ExitOnFailure(hr, "Failed to get Id"); + hr = WcaGetRecordString(hRec, eRemoveRegistryValueQuery::Root, &pRoot); + ExitOnFailure(hr, "Failed to get Root"); + hr = WcaGetRecordFormattedString(hRec, eRemoveRegistryValueQuery::Key, &pKey); + ExitOnFailure(hr, "Failed to get Key"); + hr = WcaGetRecordFormattedString(hRec, eRemoveRegistryValueQuery::Name, &pName); + ExitOnFailure(hr, "Failed to get Name"); + hr = WcaGetRecordString(hRec, eRemoveRegistryValueQuery::Area, &pArea); + ExitOnFailure(hr, "Failed to get Area"); + hr = WcaGetRecordString(hRec, eRemoveRegistryValueQuery::Condition, &pCondition); + ExitOnFailure(hr, "Failed to get Condition"); + + MSICONDITION cond = ::MsiEvaluateCondition(hInstall, pCondition); + switch (cond) + { + case MSICONDITION::MSICONDITION_NONE: + case MSICONDITION::MSICONDITION_TRUE: + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Condition evaluated true/none for %ls", pId); + break; + + case MSICONDITION::MSICONDITION_FALSE: + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Condition evaluated false for %ls", pId); + continue; + + case MSICONDITION::MSICONDITION_ERROR: + hr = E_FAIL; + ExitOnFailure(hr, "Failed to evaluate condition"); + } + + // Parse root name. + hr = CRegistryKey::ParseRoot(pRoot, &eRoot); + ExitOnFailure(hr, "Failed to parse root"); + + // Parse area name. + hr = CRegistryKey::ParseArea(pArea, &eArea); + ExitOnFailure(hr, "Failed to parse area"); + + // CustomActionData + hr = actionData.AddDeleteValue(pId, eRoot, pKey, eArea, pName); + ExitOnFailure(hr, "Failed to add 'DeleteValue' to CustomActionData"); + + // Rollback CustomActionData + hr = key.Open(eRoot, pKey, eArea, CRegistryKey::RegAccess::ReadOnly); + if (hr == E_FILENOTFOUND) + { + hr = S_OK; + continue; + } + ExitOnFailure(hr, "Failed to query existing key"); + + hr = key.GetValue(pName, &pData, &valueType, &dwValueSize); + if (hr == E_FILENOTFOUND) + { + hr = S_OK; + continue; + } + ExitOnFailure(hr, "Failed to query existing value"); + + hr = dataSerialiser.Set(pData, valueType, dwValueSize); + ExitOnFailure(hr, "Failed to initialize data serializer"); + + hr = dataSerialiser.Serialize(&pDataString); + ExitOnFailure(hr, "Failed to serialize data"); + + hr = rollbackActionData.AddCreateValue(pId, eRoot, pKey, eArea, pName, valueType, pDataString); + ExitOnFailure(hr, "Failed to create XML element"); + } + + hr = rollbackActionData.GetXmlString(&xmlString); + ExitOnFailure(hr, "Failed to read XML as text"); + hr = WcaDoDeferredAction(L"RemoveRegistryValue_rollback", xmlString, 0); + ExitOnFailure(hr, "Failed to set property"); + xmlString.Empty(); + + hr = actionData.GetXmlString(&xmlString); + ExitOnFailure(hr, "Failed to read XML as text"); + hr = WcaDoDeferredAction(L"RemoveRegistryValue_deferred", xmlString, 0); + ExitOnFailure(hr, "Failed to set property"); + xmlString.Empty(); + +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +extern "C" UINT __stdcall RemoveRegistryValue_Deferred(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + CRegistryXmlParser action; + LPWSTR pActionData = nullptr; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + hr = WcaGetProperty(L"CustomActionData", &pActionData); + ExitOnFailure(hr, "Failed to get CustomActionData"); + + hr = action.Execute(pActionData); + ExitOnFailure(hr, "Failed to parse-execute RemoveRegistryValue"); + +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} diff --git a/PanelSwCustomActions/RestartLocalResources.cpp b/src/PanelSwCustomActions/RestartLocalResources.cpp similarity index 100% rename from PanelSwCustomActions/RestartLocalResources.cpp rename to src/PanelSwCustomActions/RestartLocalResources.cpp diff --git a/PanelSwCustomActions/RestartLocalResources.h b/src/PanelSwCustomActions/RestartLocalResources.h similarity index 100% rename from PanelSwCustomActions/RestartLocalResources.h rename to src/PanelSwCustomActions/RestartLocalResources.h diff --git a/PanelSwCustomActions/Rollback.cpp b/src/PanelSwCustomActions/Rollback.cpp similarity index 96% rename from PanelSwCustomActions/Rollback.cpp rename to src/PanelSwCustomActions/Rollback.cpp index 9e6abdf6..c02335bf 100644 --- a/PanelSwCustomActions/Rollback.cpp +++ b/src/PanelSwCustomActions/Rollback.cpp @@ -1,35 +1,35 @@ -#include "pch.h" - -extern "C" UINT __stdcall Rollback(MSIHANDLE hInstall) -{ - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Rollback"); - return ERROR_INSTALL_FAILURE; -} - -extern "C" UINT __stdcall PromptCancel(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - DWORD dwRes = ERROR_SUCCESS; - PMSIHANDLE hRec; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - hRec = ::MsiCreateRecord(1); - ExitOnNull(hRec, hr, E_FAIL, "Failed creating record"); - - hr = WcaSetRecordInteger(hRec, 1, 1602); - ExitOnFailure(hr, "Failed setting record string"); - - dwRes = WcaProcessMessage((INSTALLMESSAGE)(INSTALLMESSAGE::INSTALLMESSAGE_ERROR | MB_YESNO | MB_DEFBUTTON1 | MB_ICONERROR), hRec); - if (dwRes == IDYES) - { - hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); - } - -LExit: - - dwRes = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(dwRes); +#include "pch.h" + +extern "C" UINT __stdcall Rollback(MSIHANDLE hInstall) +{ + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Rollback"); + return ERROR_INSTALL_FAILURE; +} + +extern "C" UINT __stdcall PromptCancel(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + DWORD dwRes = ERROR_SUCCESS; + PMSIHANDLE hRec; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + hRec = ::MsiCreateRecord(1); + ExitOnNull(hRec, hr, E_FAIL, "Failed creating record"); + + hr = WcaSetRecordInteger(hRec, 1, 1602); + ExitOnFailure(hr, "Failed setting record string"); + + dwRes = WcaProcessMessage((INSTALLMESSAGE)(INSTALLMESSAGE::INSTALLMESSAGE_ERROR | MB_YESNO | MB_DEFBUTTON1 | MB_ICONERROR), hRec); + if (dwRes == IDYES) + { + hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); + } + +LExit: + + dwRes = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(dwRes); } \ No newline at end of file diff --git a/PanelSwCustomActions/ServiceConfig.cpp b/src/PanelSwCustomActions/ServiceConfig.cpp similarity index 97% rename from PanelSwCustomActions/ServiceConfig.cpp rename to src/PanelSwCustomActions/ServiceConfig.cpp index 71fde556..7395de5b 100644 --- a/PanelSwCustomActions/ServiceConfig.cpp +++ b/src/PanelSwCustomActions/ServiceConfig.cpp @@ -1,442 +1,442 @@ -#include "pch.h" -#include "ServiceConfig.h" -#include "../CaCommon/RegistryKey.h" -#include "google\protobuf\any.h" -using namespace com::panelsw::ca; -using namespace google::protobuf; - -extern "C" UINT __stdcall ServiceConfig(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - DWORD dwRes = ERROR_SUCCESS; - PMSIHANDLE hView; - PMSIHANDLE hRecord; - CServiceConfig oDeferred; - CServiceConfig oRollback; - SC_HANDLE hManager = NULL; - SC_HANDLE hService = NULL; - QUERY_SERVICE_CONFIG* pServiceCfg = nullptr; - LPWSTR szDepService = nullptr; - LPWSTR szDepGroup = nullptr; - std::list lstDependencies, lstRlbkDependencies; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - // Ensure tables exist. - hr = WcaTableExists(L"PSW_ServiceConfig"); - ExitOnFailure(hr, "Failed to check if table exists 'PSW_ServiceConfig'"); - ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_ServiceConfig'. Have you authored 'PanelSw:ServiceConfig' entries in WiX code?"); - hr = WcaTableExists(L"PSW_ServiceConfig_Dependency"); - ExitOnFailure(hr, "Failed to check if table exists 'PSW_ServiceConfig_Dependency'"); - ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_ServiceConfig_Dependency'. Have you authored 'PanelSw:ServiceConfig' entries in WiX code?"); - - // Execute view - hr = WcaOpenExecuteView(L"SELECT `Id`, `Component_`, `ServiceName`, `CommandLine`, `Account`, `Password`, `Start`, `DelayStart`, `LoadOrderGroup`, `ErrorHandling` FROM `PSW_ServiceConfig`", &hView); - ExitOnFailure(hr, "Failed to execute SQL query."); - - // Open service. - hManager = ::OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT); - ExitOnNullWithLastError(hManager, hr, "Failed opening service control manager database"); - - // Iterate records - while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) - { - ExitOnFailure(hr, "Failed to fetch record."); - ReleaseNullStr(szDepGroup); - ReleaseNullStr(szDepService); - for (LPWSTR sz : lstDependencies) - { - ReleaseStr(sz); - } - lstDependencies.clear(); - lstRlbkDependencies.clear(); - - // Get fields - CWixString szId, szComponent, szServiceName, szCommand, szCommandFormat, szAccount, szPassword, szLoadOrderGroupFmt, szLoadOrderGroup; - CWixString szSubQuery; - PMSIHANDLE hSubView, hSubRecord; - int start = -1; - int nDelayStart = -1; - int errorHandling = -1; - WCA_TODO compAction = WCA_TODO_UNKNOWN; - DWORD dwServiceType = SERVICE_NO_CHANGE; - - hr = WcaGetRecordString(hRecord, 1, (LPWSTR*)szId); - ExitOnFailure(hr, "Failed to get Id."); - hr = WcaGetRecordString(hRecord, 2, (LPWSTR*)szComponent); - ExitOnFailure(hr, "Failed to get Component."); - hr = WcaGetRecordFormattedString(hRecord, 3, (LPWSTR*)szServiceName); - ExitOnFailure(hr, "Failed to get ServiceName."); - hr = WcaGetRecordString(hRecord, 4, (LPWSTR*)szCommandFormat); - ExitOnFailure(hr, "Failed to get CommandLine."); - hr = WcaGetRecordFormattedString(hRecord, 5, (LPWSTR*)szAccount); - ExitOnFailure(hr, "Failed to get Account."); - hr = WcaGetRecordFormattedString(hRecord, 6, (LPWSTR*)szPassword); - ExitOnFailure(hr, "Failed to get Password."); - hr = WcaGetRecordInteger(hRecord, 7, &start); - ExitOnFailure(hr, "Failed to get Start."); - hr = WcaGetRecordInteger(hRecord, 8, &nDelayStart); - ExitOnFailure(hr, "Failed to get DelayStart."); - hr = WcaGetRecordString(hRecord, 9, (LPWSTR*)szLoadOrderGroupFmt); - ExitOnFailure(hr, "Failed to get LoadOrderGroup."); - hr = WcaGetRecordInteger(hRecord, 10, &errorHandling); - ExitOnFailure(hr, "Failed to get ErrorHandling."); - - // Test condition - compAction = WcaGetComponentToDo(szComponent); - if (compAction != WCA_TODO::WCA_TODO_INSTALL) - { - // In case of no-action, we just check if the service is marked for deletion to notify reboot is reqired. - oDeferred.AddServiceConfig(szServiceName, nullptr, nullptr, nullptr, ServciceConfigDetails::ServiceStart::ServciceConfigDetails_ServiceStart_unchanged, nullptr, lstDependencies, ErrorHandling::ignore, ServciceConfigDetails_DelayStart::ServciceConfigDetails_DelayStart_unchanged1, SERVICE_NO_CHANGE); - - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Skipping configuration of service '%ls' since component is not installed", (LPCWSTR)szServiceName); - continue; - } - - if (!szCommandFormat.IsNullOrEmpty()) - { - hr = szCommand.MsiFormat(szCommandFormat); - ExitOnFailure(hr, "Failed formatting string"); - - CDeferredActionBase::LogUnformatted(LOGLEVEL::LOGMSG_STANDARD, false, L"Will configure service '%ls' to execute command line '%ls'", (LPCWSTR)szServiceName, szCommand.Obfuscated()); - } - if (!szAccount.IsNullOrEmpty()) - { - // Ensure account format is domain\user - DWORD i = szAccount.Find(L'@'); - if (i != INFINITE) - { - CWixString szDomain, szName; - - hr = szDomain.Copy(((LPCWSTR)szAccount) + i + 1); - ExitOnFailure(hr, "Failed copying string"); - - hr = szName.Copy((LPCWSTR)szAccount, i); - ExitOnFailure(hr, "Failed copying string"); - - szAccount.Format(L"%ls\\%ls", (LPCWSTR)szDomain, (LPCWSTR)szName); - ExitOnFailure(hr, "Failed formatting string"); - } - else - { - // Set computer name as domain part if not specified - i = szAccount.Find(L'\\'); - if (i == INFINITE) - { - CWixString szDomain, szName; - - hr = WcaGetProperty(L"ComputerName", (LPWSTR*)szDomain); - ExitOnFailure(hr, "Failed getting 'ComputerName' property"); - - hr = szName.Copy((LPCWSTR)szAccount); - ExitOnFailure(hr, "Failed copying string"); - - szAccount.Format(L"%ls\\%ls", (LPCWSTR)szDomain, (LPCWSTR)szName); - ExitOnFailure(hr, "Failed formatting string"); - } - } - - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will change service '%ls' start account to '%ls'", (LPCWSTR)szServiceName, (LPCWSTR)szAccount); - } - if (start != ServciceConfigDetails_ServiceStart::ServciceConfigDetails_ServiceStart_unchanged) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will change service '%ls' start type to %i", (LPCWSTR)szServiceName, start); - } - if (!szLoadOrderGroupFmt.IsNullOrEmpty()) - { - hr = szLoadOrderGroup.MsiFormat(szLoadOrderGroupFmt); - ExitOnFailure(hr, "Failed formatting string"); - - if (szLoadOrderGroup.IsNullOrEmpty()) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will clear service '%ls' load order group", (LPCWSTR)szServiceName); - } - else - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will change service '%ls' load order group to '%ls'", (LPCWSTR)szServiceName, (LPCWSTR)szLoadOrderGroup); - } - } - - // Dependencies - hr = szSubQuery.Format(L"SELECT `Service`, `Group` FROM `PSW_ServiceConfig_Dependency` WHERE `ServiceConfig_`='%ls'", (LPCWSTR)szId); - ExitOnFailure(hr, "Failed to format string"); - - hr = WcaOpenExecuteView((LPCWSTR)szSubQuery, &hSubView); - ExitOnFailure(hr, "Failed to execute SQL query '%ls'.", (LPCWSTR)szSubQuery); - - // Iterate records - while ((hr = WcaFetchRecord(hSubView, &hSubRecord)) != E_NOMOREITEMS) - { - ExitOnFailure(hr, "Failed to fetch record."); - ReleaseNullStr(szDepGroup); - ReleaseNullStr(szDepService); - CWixString szGroup; - - hr = WcaGetRecordFormattedString(hSubRecord, 1, &szDepService); - ExitOnFailure(hr, "Failed to get Dependency."); - hr = WcaGetRecordFormattedString(hSubRecord, 2, (LPWSTR*)szGroup); - ExitOnFailure(hr, "Failed to get Group."); - - if (!szGroup.IsNullOrEmpty()) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will add to service '%ls' dependency on group '%ls'", (LPCWSTR)szServiceName, (LPCWSTR)szGroup); - - hr = StrAllocFormatted(&szDepGroup, L"%lc%ls", SC_GROUP_IDENTIFIER, (LPCWSTR)szGroup); - ExitOnFailure(hr, "Failed allocating string"); - - lstDependencies.push_back(szDepGroup); - szDepGroup = nullptr; - } - - if (szDepService && *szDepService) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will add to service '%ls' dependency on service '%ls'", (LPCWSTR)szServiceName, szDepService); - lstDependencies.push_back(szDepService); - szDepService = nullptr; - } - } - - // Get current service account. - hService = ::OpenService(hManager, (LPCWSTR)szServiceName, SERVICE_QUERY_CONFIG); - if (hService) // Won't fail if service doesn't exist - { - DWORD dwSize = 0; - ServciceConfigDetails_DelayStart rlbkDelayStart = ServciceConfigDetails_DelayStart::ServciceConfigDetails_DelayStart_unchanged1; - - dwRes = ::QueryServiceConfig(hService, nullptr, 0, &dwSize); - ExitOnNullWithLastError((dwRes || (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)), hr, "Failed querying service '%ls' configuration size", (LPCWSTR)szServiceName); - - pServiceCfg = (QUERY_SERVICE_CONFIG*)MemAlloc(dwSize, FALSE); - ExitOnNull(pServiceCfg, hr, E_FAIL, "Failed allocating memory"); - - dwRes = ::QueryServiceConfig(hService, pServiceCfg, dwSize, &dwSize); - ExitOnNullWithLastError(dwRes, hr, "Failed querying service '%ls' configuration", (LPCWSTR)szServiceName); - - // If service is interactive, may need to change the type. - if (!szAccount.IsNullOrEmpty() && !szAccount.EqualsIgnoreCase(L".\\LocalSystem") && ((pServiceCfg->dwServiceType & SERVICE_INTERACTIVE_PROCESS) == SERVICE_INTERACTIVE_PROCESS)) - { - dwServiceType = (pServiceCfg->dwServiceType & ~SERVICE_INTERACTIVE_PROCESS); - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will change service '%ls' type to 0x%08X", (LPCWSTR)szServiceName, dwServiceType); - } - - if (start == ServciceConfigDetails::ServiceStart::ServciceConfigDetails_ServiceStart_unchanged) - { - pServiceCfg->dwStartType = SERVICE_NO_CHANGE; - } - if (start == ServciceConfigDetails::ServiceStart::ServciceConfigDetails_ServiceStart_auto_) - { - SERVICE_DELAYED_AUTO_START_INFO delayStart; - DWORD dwJunk = 0; - - dwRes = ::QueryServiceConfig2(hService, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, (LPBYTE)&delayStart, sizeof(delayStart), &dwJunk); - ExitOnNullWithLastError(dwRes, hr, "Failed querying service '%ls' delay-start info", (LPCWSTR)szServiceName); - - rlbkDelayStart = delayStart.fDelayedAutostart ? ServciceConfigDetails_DelayStart::ServciceConfigDetails_DelayStart_yes : ServciceConfigDetails_DelayStart::ServciceConfigDetails_DelayStart_no; - } - if (pServiceCfg->lpDependencies) - { - for (LPWSTR sz = pServiceCfg->lpDependencies; sz && *sz; sz += 1 + wcslen(sz)) - { - lstRlbkDependencies.push_back(sz); - } - } - - hr = oRollback.AddServiceConfig((LPCWSTR)szServiceName, pServiceCfg->lpBinaryPathName, pServiceCfg->lpServiceStartName, nullptr, pServiceCfg->dwStartType, pServiceCfg->lpLoadOrderGroup, lstRlbkDependencies, ErrorHandling::ignore, rlbkDelayStart, pServiceCfg->dwServiceType); - ExitOnFailure(hr, "Failed creating rollback CustomActionData"); - - ReleaseNullMem(pServiceCfg); - ReleaseServiceHandle(hService); - } - - hr = oDeferred.AddServiceConfig(szServiceName, szCommand, szAccount, szPassword, start, szLoadOrderGroup, lstDependencies, (ErrorHandling)errorHandling, (ServciceConfigDetails_DelayStart)nDelayStart, dwServiceType); - ExitOnFailure(hr, "Failed creating CustomActionData"); - } - - // Set CAD - hr = oRollback.DoDeferredAction(L"PSW_ServiceConfigRlbk"); - ExitOnFailure(hr, "Failed setting rollback action data."); - - hr = oDeferred.DoDeferredAction(L"PSW_ServiceConfigExec"); - ExitOnFailure(hr, "Failed setting action data."); - -LExit: - ReleaseStr(szDepGroup); - ReleaseStr(szDepService); - ReleaseNullMem(pServiceCfg); - ReleaseServiceHandle(hService); - ReleaseServiceHandle(hManager); - for (LPWSTR sz : lstDependencies) - { - ReleaseStr(sz); - } - - dwRes = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(dwRes); -} - -CServiceConfig::CServiceConfig() - : CDeferredActionBase("ServiceConfig") - , _errorPrompter(PSW_MSI_MESSAGES::PSW_MSI_MESSAGES_SERVICE_CONFIG_ERROR) -{ } - -HRESULT CServiceConfig::AddServiceConfig(LPCWSTR szServiceName, LPCWSTR szCommandLine, LPCWSTR szAccount, LPCWSTR szPassword, int start, LPCWSTR szLoadOrderGroup, const std::list &lstDependencies, ErrorHandling errorHandling, ServciceConfigDetails_DelayStart delayStart, DWORD dwServiceType) -{ - HRESULT hr = S_OK; - ::com::panelsw::ca::Command* pCmd = nullptr; - ServciceConfigDetails* pDetails = nullptr; - ::std::string* pAny = nullptr; - bool bRes = true; - - hr = AddCommand("CServiceConfig", &pCmd); - ExitOnFailure(hr, "Failed to add command"); - - pDetails = new ServciceConfigDetails(); - ExitOnNull(pDetails, hr, E_FAIL, "Failed allocating details"); - - pDetails->set_name(szServiceName, WSTR_BYTE_SIZE(szServiceName)); - if (szAccount && *szAccount) - { - pDetails->set_account(szAccount, WSTR_BYTE_SIZE(szAccount)); - if (szPassword && *szPassword) - { - pDetails->set_password(szPassword, WSTR_BYTE_SIZE(szPassword)); - } - } - if (szCommandLine && *szCommandLine) - { - pDetails->set_commandline(szCommandLine, WSTR_BYTE_SIZE(szCommandLine)); - } - if (szLoadOrderGroup) // May be empty - { - pDetails->set_loadordergroup(szLoadOrderGroup, WSTR_BYTE_SIZE(szLoadOrderGroup)); - } - for (const LPCWSTR szDep : lstDependencies) - { - pDetails->add_dependencies(szDep, WSTR_BYTE_SIZE(szDep)); - } - pDetails->set_start((ServciceConfigDetails::ServiceStart)start); - pDetails->set_delaystart(delayStart); - pDetails->set_errorhandling((ErrorHandling)errorHandling); - pDetails->set_servicetype(dwServiceType); - - pAny = pCmd->mutable_details(); - ExitOnNull(pAny, hr, E_FAIL, "Failed allocating any"); - - bRes = pDetails->SerializeToString(pAny); - ExitOnNull(bRes, hr, E_FAIL, "Failed serializing command details"); - -LExit: - return hr; -} - -HRESULT CServiceConfig::DeferredExecute(const ::std::string& command) -{ - HRESULT hr = S_OK; - LPCWSTR szServiceName = nullptr; - LPCWSTR szCommandLine = nullptr; - LPCWSTR szAccount = nullptr; - LPCWSTR szPassword = nullptr; - LPCWSTR szLoadOrderGroup = nullptr; - LPWSTR szDependencies = nullptr; - DWORD bRes = TRUE; - ServciceConfigDetails details; - - bRes = details.ParseFromString(command); - ExitOnNull(bRes, hr, E_INVALIDARG, "Failed unpacking ExecOnDetails"); - - szServiceName = (LPCWSTR)(LPVOID)details.name().data(); - if (details.account().size() > sizeof(WCHAR)) // Larger than NULL - { - szAccount = (LPCWSTR)(LPVOID)details.account().data(); - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Service '%ls' account '%ls'", szServiceName, szAccount); - - if (details.password().size() > sizeof(WCHAR))// Larger than NULL - { - szPassword = (LPCWSTR)(LPVOID)details.password().data(); - } - } - if (details.commandline().size() > sizeof(WCHAR)) - { - szCommandLine = (LPCWSTR)(LPVOID)details.commandline().data(); - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Service '%ls' command line '%ls'", szServiceName, szCommandLine); - } - if (details.loadordergroup().size() > 0) // May be empty - { - szLoadOrderGroup = (LPCWSTR)(LPVOID)details.loadordergroup().data(); - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Service '%ls' load order group '%ls'", szServiceName, szLoadOrderGroup); - } - for (const std::string dep : details.dependencies()) - { - LPCWSTR szDep = (LPCWSTR)(LPVOID)dep.data(); - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Service '%ls' dependency '%ls'", szServiceName, szDep); - if (szDependencies) - { - hr = MultiSzPrepend(&szDependencies, nullptr, szDep); - ExitOnFailure(hr, "Failed to allocate string"); - } - else - { - hr = StrAllocFormatted(&szDependencies, L"%ls%lc", szDep, L'\0'); - ExitOnFailure(hr, "Failed to allocate string"); - } - } - - do - { - hr = ExecuteOne(szServiceName, szCommandLine, szAccount, szPassword, details.start(), szLoadOrderGroup, szDependencies, details.delaystart(), details.servicetype()); - if (FAILED(hr)) - { - _errorPrompter.SetErrorHandling((PSW_ERROR_HANDLING)details.errorhandling()); - hr = _errorPrompter.Prompt(szServiceName); - } - } while (hr == E_RETRY); - ExitOnFailure(hr, "Failed configuring service '%ls'", szServiceName); - -LExit: - ReleaseStr(szDependencies); - return hr; -} - -HRESULT CServiceConfig::ExecuteOne(LPCWSTR szServiceName, LPCWSTR szCommandLine, LPCWSTR szAccount, LPCWSTR szPassword, DWORD dwStart, LPCWSTR szLoadOrderGroup, LPCWSTR szDependencies, ServciceConfigDetails_DelayStart nDelayStart, DWORD dwServiceType) -{ - HRESULT hr = S_OK; - SC_HANDLE hManager = NULL; - SC_HANDLE hService = NULL; - DWORD dwRes = ERROR_SUCCESS; - - // Open service. - hManager = ::OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); - ExitOnNullWithLastError(hManager, hr, "Failed opening service control manager database"); - - hService = ::OpenService(hManager, szServiceName, SERVICE_ALL_ACCESS); - ExitOnNullWithLastError(hService, hr, "Failed opening service '%ls'", szServiceName); - - // Configure. - dwRes = ::ChangeServiceConfig(hService, dwServiceType, dwStart, SERVICE_NO_CHANGE, szCommandLine, szLoadOrderGroup, nullptr, szDependencies, szAccount, szPassword, nullptr); - if (!dwRes && (::GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE)) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Service '%ls' is marked for deletion- reboot is required", szServiceName); - hr = WcaDeferredActionRequiresReboot(); - ExitOnFailure(hr, "Failed requiring reboot"); - hr = S_FALSE; - ExitFunction(); - } - ExitOnNullWithLastError(dwRes, hr, "Failed configuring service '%ls'", szServiceName); - - if ((dwStart == SERVICE_AUTO_START) && (nDelayStart != ServciceConfigDetails_DelayStart::ServciceConfigDetails_DelayStart_unchanged1)) - { - SERVICE_DELAYED_AUTO_START_INFO delayStart; - delayStart.fDelayedAutostart = (nDelayStart == ServciceConfigDetails_DelayStart::ServciceConfigDetails_DelayStart_yes) ? TRUE : FALSE; - - dwRes = ::ChangeServiceConfig2(hService, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, &delayStart); - ExitOnNullWithLastError(dwRes, hr, "Failed setting service '%ls' delay-start mode", szServiceName); - } - -LExit: - - ReleaseServiceHandle(hService); - ReleaseServiceHandle(hManager); - return hr; -} +#include "pch.h" +#include "ServiceConfig.h" +#include "../CaCommon/RegistryKey.h" +#include "google\protobuf\any.h" +using namespace com::panelsw::ca; +using namespace google::protobuf; + +extern "C" UINT __stdcall ServiceConfig(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + DWORD dwRes = ERROR_SUCCESS; + PMSIHANDLE hView; + PMSIHANDLE hRecord; + CServiceConfig oDeferred; + CServiceConfig oRollback; + SC_HANDLE hManager = NULL; + SC_HANDLE hService = NULL; + QUERY_SERVICE_CONFIG* pServiceCfg = nullptr; + LPWSTR szDepService = nullptr; + LPWSTR szDepGroup = nullptr; + std::list lstDependencies, lstRlbkDependencies; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + // Ensure tables exist. + hr = WcaTableExists(L"PSW_ServiceConfig"); + ExitOnFailure(hr, "Failed to check if table exists 'PSW_ServiceConfig'"); + ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_ServiceConfig'. Have you authored 'PanelSw:ServiceConfig' entries in WiX code?"); + hr = WcaTableExists(L"PSW_ServiceConfig_Dependency"); + ExitOnFailure(hr, "Failed to check if table exists 'PSW_ServiceConfig_Dependency'"); + ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_ServiceConfig_Dependency'. Have you authored 'PanelSw:ServiceConfig' entries in WiX code?"); + + // Execute view + hr = WcaOpenExecuteView(L"SELECT `Id`, `Component_`, `ServiceName`, `CommandLine`, `Account`, `Password`, `Start`, `DelayStart`, `LoadOrderGroup`, `ErrorHandling` FROM `PSW_ServiceConfig`", &hView); + ExitOnFailure(hr, "Failed to execute SQL query."); + + // Open service. + hManager = ::OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT); + ExitOnNullWithLastError(hManager, hr, "Failed opening service control manager database"); + + // Iterate records + while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) + { + ExitOnFailure(hr, "Failed to fetch record."); + ReleaseNullStr(szDepGroup); + ReleaseNullStr(szDepService); + for (LPWSTR sz : lstDependencies) + { + ReleaseStr(sz); + } + lstDependencies.clear(); + lstRlbkDependencies.clear(); + + // Get fields + CWixString szId, szComponent, szServiceName, szCommand, szCommandFormat, szAccount, szPassword, szLoadOrderGroupFmt, szLoadOrderGroup; + CWixString szSubQuery; + PMSIHANDLE hSubView, hSubRecord; + int start = -1; + int nDelayStart = -1; + int errorHandling = -1; + WCA_TODO compAction = WCA_TODO_UNKNOWN; + DWORD dwServiceType = SERVICE_NO_CHANGE; + + hr = WcaGetRecordString(hRecord, 1, (LPWSTR*)szId); + ExitOnFailure(hr, "Failed to get Id."); + hr = WcaGetRecordString(hRecord, 2, (LPWSTR*)szComponent); + ExitOnFailure(hr, "Failed to get Component."); + hr = WcaGetRecordFormattedString(hRecord, 3, (LPWSTR*)szServiceName); + ExitOnFailure(hr, "Failed to get ServiceName."); + hr = WcaGetRecordString(hRecord, 4, (LPWSTR*)szCommandFormat); + ExitOnFailure(hr, "Failed to get CommandLine."); + hr = WcaGetRecordFormattedString(hRecord, 5, (LPWSTR*)szAccount); + ExitOnFailure(hr, "Failed to get Account."); + hr = WcaGetRecordFormattedString(hRecord, 6, (LPWSTR*)szPassword); + ExitOnFailure(hr, "Failed to get Password."); + hr = WcaGetRecordInteger(hRecord, 7, &start); + ExitOnFailure(hr, "Failed to get Start."); + hr = WcaGetRecordInteger(hRecord, 8, &nDelayStart); + ExitOnFailure(hr, "Failed to get DelayStart."); + hr = WcaGetRecordString(hRecord, 9, (LPWSTR*)szLoadOrderGroupFmt); + ExitOnFailure(hr, "Failed to get LoadOrderGroup."); + hr = WcaGetRecordInteger(hRecord, 10, &errorHandling); + ExitOnFailure(hr, "Failed to get ErrorHandling."); + + // Test condition + compAction = WcaGetComponentToDo(szComponent); + if (compAction != WCA_TODO::WCA_TODO_INSTALL) + { + // In case of no-action, we just check if the service is marked for deletion to notify reboot is reqired. + oDeferred.AddServiceConfig(szServiceName, nullptr, nullptr, nullptr, ServciceConfigDetails::ServiceStart::ServciceConfigDetails_ServiceStart_unchanged, nullptr, lstDependencies, ErrorHandling::ignore, ServciceConfigDetails_DelayStart::ServciceConfigDetails_DelayStart_unchanged1, SERVICE_NO_CHANGE); + + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Skipping configuration of service '%ls' since component is not installed", (LPCWSTR)szServiceName); + continue; + } + + if (!szCommandFormat.IsNullOrEmpty()) + { + hr = szCommand.MsiFormat(szCommandFormat); + ExitOnFailure(hr, "Failed formatting string"); + + CDeferredActionBase::LogUnformatted(LOGLEVEL::LOGMSG_STANDARD, false, L"Will configure service '%ls' to execute command line '%ls'", (LPCWSTR)szServiceName, szCommand.Obfuscated()); + } + if (!szAccount.IsNullOrEmpty()) + { + // Ensure account format is domain\user + DWORD i = szAccount.Find(L'@'); + if (i != INFINITE) + { + CWixString szDomain, szName; + + hr = szDomain.Copy(((LPCWSTR)szAccount) + i + 1); + ExitOnFailure(hr, "Failed copying string"); + + hr = szName.Copy((LPCWSTR)szAccount, i); + ExitOnFailure(hr, "Failed copying string"); + + szAccount.Format(L"%ls\\%ls", (LPCWSTR)szDomain, (LPCWSTR)szName); + ExitOnFailure(hr, "Failed formatting string"); + } + else + { + // Set computer name as domain part if not specified + i = szAccount.Find(L'\\'); + if (i == INFINITE) + { + CWixString szDomain, szName; + + hr = WcaGetProperty(L"ComputerName", (LPWSTR*)szDomain); + ExitOnFailure(hr, "Failed getting 'ComputerName' property"); + + hr = szName.Copy((LPCWSTR)szAccount); + ExitOnFailure(hr, "Failed copying string"); + + szAccount.Format(L"%ls\\%ls", (LPCWSTR)szDomain, (LPCWSTR)szName); + ExitOnFailure(hr, "Failed formatting string"); + } + } + + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will change service '%ls' start account to '%ls'", (LPCWSTR)szServiceName, (LPCWSTR)szAccount); + } + if (start != ServciceConfigDetails_ServiceStart::ServciceConfigDetails_ServiceStart_unchanged) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will change service '%ls' start type to %i", (LPCWSTR)szServiceName, start); + } + if (!szLoadOrderGroupFmt.IsNullOrEmpty()) + { + hr = szLoadOrderGroup.MsiFormat(szLoadOrderGroupFmt); + ExitOnFailure(hr, "Failed formatting string"); + + if (szLoadOrderGroup.IsNullOrEmpty()) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will clear service '%ls' load order group", (LPCWSTR)szServiceName); + } + else + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will change service '%ls' load order group to '%ls'", (LPCWSTR)szServiceName, (LPCWSTR)szLoadOrderGroup); + } + } + + // Dependencies + hr = szSubQuery.Format(L"SELECT `Service`, `Group` FROM `PSW_ServiceConfig_Dependency` WHERE `ServiceConfig_`='%ls'", (LPCWSTR)szId); + ExitOnFailure(hr, "Failed to format string"); + + hr = WcaOpenExecuteView((LPCWSTR)szSubQuery, &hSubView); + ExitOnFailure(hr, "Failed to execute SQL query '%ls'.", (LPCWSTR)szSubQuery); + + // Iterate records + while ((hr = WcaFetchRecord(hSubView, &hSubRecord)) != E_NOMOREITEMS) + { + ExitOnFailure(hr, "Failed to fetch record."); + ReleaseNullStr(szDepGroup); + ReleaseNullStr(szDepService); + CWixString szGroup; + + hr = WcaGetRecordFormattedString(hSubRecord, 1, &szDepService); + ExitOnFailure(hr, "Failed to get Dependency."); + hr = WcaGetRecordFormattedString(hSubRecord, 2, (LPWSTR*)szGroup); + ExitOnFailure(hr, "Failed to get Group."); + + if (!szGroup.IsNullOrEmpty()) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will add to service '%ls' dependency on group '%ls'", (LPCWSTR)szServiceName, (LPCWSTR)szGroup); + + hr = StrAllocFormatted(&szDepGroup, L"%lc%ls", SC_GROUP_IDENTIFIER, (LPCWSTR)szGroup); + ExitOnFailure(hr, "Failed allocating string"); + + lstDependencies.push_back(szDepGroup); + szDepGroup = nullptr; + } + + if (szDepService && *szDepService) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will add to service '%ls' dependency on service '%ls'", (LPCWSTR)szServiceName, szDepService); + lstDependencies.push_back(szDepService); + szDepService = nullptr; + } + } + + // Get current service account. + hService = ::OpenService(hManager, (LPCWSTR)szServiceName, SERVICE_QUERY_CONFIG); + if (hService) // Won't fail if service doesn't exist + { + DWORD dwSize = 0; + ServciceConfigDetails_DelayStart rlbkDelayStart = ServciceConfigDetails_DelayStart::ServciceConfigDetails_DelayStart_unchanged1; + + dwRes = ::QueryServiceConfig(hService, nullptr, 0, &dwSize); + ExitOnNullWithLastError((dwRes || (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)), hr, "Failed querying service '%ls' configuration size", (LPCWSTR)szServiceName); + + pServiceCfg = (QUERY_SERVICE_CONFIG*)MemAlloc(dwSize, FALSE); + ExitOnNull(pServiceCfg, hr, E_FAIL, "Failed allocating memory"); + + dwRes = ::QueryServiceConfig(hService, pServiceCfg, dwSize, &dwSize); + ExitOnNullWithLastError(dwRes, hr, "Failed querying service '%ls' configuration", (LPCWSTR)szServiceName); + + // If service is interactive, may need to change the type. + if (!szAccount.IsNullOrEmpty() && !szAccount.EqualsIgnoreCase(L".\\LocalSystem") && ((pServiceCfg->dwServiceType & SERVICE_INTERACTIVE_PROCESS) == SERVICE_INTERACTIVE_PROCESS)) + { + dwServiceType = (pServiceCfg->dwServiceType & ~SERVICE_INTERACTIVE_PROCESS); + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will change service '%ls' type to 0x%08X", (LPCWSTR)szServiceName, dwServiceType); + } + + if (start == ServciceConfigDetails::ServiceStart::ServciceConfigDetails_ServiceStart_unchanged) + { + pServiceCfg->dwStartType = SERVICE_NO_CHANGE; + } + if (start == ServciceConfigDetails::ServiceStart::ServciceConfigDetails_ServiceStart_auto_) + { + SERVICE_DELAYED_AUTO_START_INFO delayStart; + DWORD dwJunk = 0; + + dwRes = ::QueryServiceConfig2(hService, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, (LPBYTE)&delayStart, sizeof(delayStart), &dwJunk); + ExitOnNullWithLastError(dwRes, hr, "Failed querying service '%ls' delay-start info", (LPCWSTR)szServiceName); + + rlbkDelayStart = delayStart.fDelayedAutostart ? ServciceConfigDetails_DelayStart::ServciceConfigDetails_DelayStart_yes : ServciceConfigDetails_DelayStart::ServciceConfigDetails_DelayStart_no; + } + if (pServiceCfg->lpDependencies) + { + for (LPWSTR sz = pServiceCfg->lpDependencies; sz && *sz; sz += 1 + wcslen(sz)) + { + lstRlbkDependencies.push_back(sz); + } + } + + hr = oRollback.AddServiceConfig((LPCWSTR)szServiceName, pServiceCfg->lpBinaryPathName, pServiceCfg->lpServiceStartName, nullptr, pServiceCfg->dwStartType, pServiceCfg->lpLoadOrderGroup, lstRlbkDependencies, ErrorHandling::ignore, rlbkDelayStart, pServiceCfg->dwServiceType); + ExitOnFailure(hr, "Failed creating rollback CustomActionData"); + + ReleaseNullMem(pServiceCfg); + ReleaseServiceHandle(hService); + } + + hr = oDeferred.AddServiceConfig(szServiceName, szCommand, szAccount, szPassword, start, szLoadOrderGroup, lstDependencies, (ErrorHandling)errorHandling, (ServciceConfigDetails_DelayStart)nDelayStart, dwServiceType); + ExitOnFailure(hr, "Failed creating CustomActionData"); + } + + // Set CAD + hr = oRollback.DoDeferredAction(L"PSW_ServiceConfigRlbk"); + ExitOnFailure(hr, "Failed setting rollback action data."); + + hr = oDeferred.DoDeferredAction(L"PSW_ServiceConfigExec"); + ExitOnFailure(hr, "Failed setting action data."); + +LExit: + ReleaseStr(szDepGroup); + ReleaseStr(szDepService); + ReleaseNullMem(pServiceCfg); + ReleaseServiceHandle(hService); + ReleaseServiceHandle(hManager); + for (LPWSTR sz : lstDependencies) + { + ReleaseStr(sz); + } + + dwRes = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(dwRes); +} + +CServiceConfig::CServiceConfig() + : CDeferredActionBase("ServiceConfig") + , _errorPrompter(PSW_MSI_MESSAGES::PSW_MSI_MESSAGES_SERVICE_CONFIG_ERROR) +{ } + +HRESULT CServiceConfig::AddServiceConfig(LPCWSTR szServiceName, LPCWSTR szCommandLine, LPCWSTR szAccount, LPCWSTR szPassword, int start, LPCWSTR szLoadOrderGroup, const std::list &lstDependencies, ErrorHandling errorHandling, ServciceConfigDetails_DelayStart delayStart, DWORD dwServiceType) +{ + HRESULT hr = S_OK; + ::com::panelsw::ca::Command* pCmd = nullptr; + ServciceConfigDetails* pDetails = nullptr; + ::std::string* pAny = nullptr; + bool bRes = true; + + hr = AddCommand("CServiceConfig", &pCmd); + ExitOnFailure(hr, "Failed to add command"); + + pDetails = new ServciceConfigDetails(); + ExitOnNull(pDetails, hr, E_FAIL, "Failed allocating details"); + + pDetails->set_name(szServiceName, WSTR_BYTE_SIZE(szServiceName)); + if (szAccount && *szAccount) + { + pDetails->set_account(szAccount, WSTR_BYTE_SIZE(szAccount)); + if (szPassword && *szPassword) + { + pDetails->set_password(szPassword, WSTR_BYTE_SIZE(szPassword)); + } + } + if (szCommandLine && *szCommandLine) + { + pDetails->set_commandline(szCommandLine, WSTR_BYTE_SIZE(szCommandLine)); + } + if (szLoadOrderGroup) // May be empty + { + pDetails->set_loadordergroup(szLoadOrderGroup, WSTR_BYTE_SIZE(szLoadOrderGroup)); + } + for (const LPCWSTR szDep : lstDependencies) + { + pDetails->add_dependencies(szDep, WSTR_BYTE_SIZE(szDep)); + } + pDetails->set_start((ServciceConfigDetails::ServiceStart)start); + pDetails->set_delaystart(delayStart); + pDetails->set_errorhandling((ErrorHandling)errorHandling); + pDetails->set_servicetype(dwServiceType); + + pAny = pCmd->mutable_details(); + ExitOnNull(pAny, hr, E_FAIL, "Failed allocating any"); + + bRes = pDetails->SerializeToString(pAny); + ExitOnNull(bRes, hr, E_FAIL, "Failed serializing command details"); + +LExit: + return hr; +} + +HRESULT CServiceConfig::DeferredExecute(const ::std::string& command) +{ + HRESULT hr = S_OK; + LPCWSTR szServiceName = nullptr; + LPCWSTR szCommandLine = nullptr; + LPCWSTR szAccount = nullptr; + LPCWSTR szPassword = nullptr; + LPCWSTR szLoadOrderGroup = nullptr; + LPWSTR szDependencies = nullptr; + DWORD bRes = TRUE; + ServciceConfigDetails details; + + bRes = details.ParseFromString(command); + ExitOnNull(bRes, hr, E_INVALIDARG, "Failed unpacking ExecOnDetails"); + + szServiceName = (LPCWSTR)(LPVOID)details.name().data(); + if (details.account().size() > sizeof(WCHAR)) // Larger than NULL + { + szAccount = (LPCWSTR)(LPVOID)details.account().data(); + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Service '%ls' account '%ls'", szServiceName, szAccount); + + if (details.password().size() > sizeof(WCHAR))// Larger than NULL + { + szPassword = (LPCWSTR)(LPVOID)details.password().data(); + } + } + if (details.commandline().size() > sizeof(WCHAR)) + { + szCommandLine = (LPCWSTR)(LPVOID)details.commandline().data(); + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Service '%ls' command line '%ls'", szServiceName, szCommandLine); + } + if (details.loadordergroup().size() > 0) // May be empty + { + szLoadOrderGroup = (LPCWSTR)(LPVOID)details.loadordergroup().data(); + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Service '%ls' load order group '%ls'", szServiceName, szLoadOrderGroup); + } + for (const std::string dep : details.dependencies()) + { + LPCWSTR szDep = (LPCWSTR)(LPVOID)dep.data(); + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Service '%ls' dependency '%ls'", szServiceName, szDep); + if (szDependencies) + { + hr = MultiSzPrepend(&szDependencies, nullptr, szDep); + ExitOnFailure(hr, "Failed to allocate string"); + } + else + { + hr = StrAllocFormatted(&szDependencies, L"%ls%lc", szDep, L'\0'); + ExitOnFailure(hr, "Failed to allocate string"); + } + } + + do + { + hr = ExecuteOne(szServiceName, szCommandLine, szAccount, szPassword, details.start(), szLoadOrderGroup, szDependencies, details.delaystart(), details.servicetype()); + if (FAILED(hr)) + { + _errorPrompter.SetErrorHandling((PSW_ERROR_HANDLING)details.errorhandling()); + hr = _errorPrompter.Prompt(szServiceName); + } + } while (hr == E_RETRY); + ExitOnFailure(hr, "Failed configuring service '%ls'", szServiceName); + +LExit: + ReleaseStr(szDependencies); + return hr; +} + +HRESULT CServiceConfig::ExecuteOne(LPCWSTR szServiceName, LPCWSTR szCommandLine, LPCWSTR szAccount, LPCWSTR szPassword, DWORD dwStart, LPCWSTR szLoadOrderGroup, LPCWSTR szDependencies, ServciceConfigDetails_DelayStart nDelayStart, DWORD dwServiceType) +{ + HRESULT hr = S_OK; + SC_HANDLE hManager = NULL; + SC_HANDLE hService = NULL; + DWORD dwRes = ERROR_SUCCESS; + + // Open service. + hManager = ::OpenSCManager(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); + ExitOnNullWithLastError(hManager, hr, "Failed opening service control manager database"); + + hService = ::OpenService(hManager, szServiceName, SERVICE_ALL_ACCESS); + ExitOnNullWithLastError(hService, hr, "Failed opening service '%ls'", szServiceName); + + // Configure. + dwRes = ::ChangeServiceConfig(hService, dwServiceType, dwStart, SERVICE_NO_CHANGE, szCommandLine, szLoadOrderGroup, nullptr, szDependencies, szAccount, szPassword, nullptr); + if (!dwRes && (::GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE)) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Service '%ls' is marked for deletion- reboot is required", szServiceName); + hr = WcaDeferredActionRequiresReboot(); + ExitOnFailure(hr, "Failed requiring reboot"); + hr = S_FALSE; + ExitFunction(); + } + ExitOnNullWithLastError(dwRes, hr, "Failed configuring service '%ls'", szServiceName); + + if ((dwStart == SERVICE_AUTO_START) && (nDelayStart != ServciceConfigDetails_DelayStart::ServciceConfigDetails_DelayStart_unchanged1)) + { + SERVICE_DELAYED_AUTO_START_INFO delayStart; + delayStart.fDelayedAutostart = (nDelayStart == ServciceConfigDetails_DelayStart::ServciceConfigDetails_DelayStart_yes) ? TRUE : FALSE; + + dwRes = ::ChangeServiceConfig2(hService, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, &delayStart); + ExitOnNullWithLastError(dwRes, hr, "Failed setting service '%ls' delay-start mode", szServiceName); + } + +LExit: + + ReleaseServiceHandle(hService); + ReleaseServiceHandle(hManager); + return hr; +} diff --git a/PanelSwCustomActions/ServiceConfig.h b/src/PanelSwCustomActions/ServiceConfig.h similarity index 100% rename from PanelSwCustomActions/ServiceConfig.h rename to src/PanelSwCustomActions/ServiceConfig.h diff --git a/PanelSwCustomActions/SetPropertyFromPipe.cpp b/src/PanelSwCustomActions/SetPropertyFromPipe.cpp similarity index 100% rename from PanelSwCustomActions/SetPropertyFromPipe.cpp rename to src/PanelSwCustomActions/SetPropertyFromPipe.cpp diff --git a/PanelSwCustomActions/ShellExecute.cpp b/src/PanelSwCustomActions/ShellExecute.cpp similarity index 97% rename from PanelSwCustomActions/ShellExecute.cpp rename to src/PanelSwCustomActions/ShellExecute.cpp index d6d7d19a..a69d79c9 100644 --- a/PanelSwCustomActions/ShellExecute.cpp +++ b/src/PanelSwCustomActions/ShellExecute.cpp @@ -1,262 +1,262 @@ -#include "pch.h" -#include "ShellExecute.h" -#include -#include "shellExecDetails.pb.h" -using namespace ::com::panelsw::ca; -using namespace google::protobuf; -#pragma comment (lib, "Shell32.lib") - - -#define ShellExecute_QUERY L"SELECT `Id`, `Target`, `Args`, `Verb`, `WorkingDir`, `Show`, `Wait`, `Flags`, `Condition` FROM `PSW_ShellExecute`" -enum ShellExecuteQuery { Id=1, Target=2, Args=3, Verb=4, WorkingDir=5, Show=6, Wait=7, Flags=8, Condition=9 }; - -enum ShellExecuteFlags -{ - None = 0, - OnExecute = 1, - OnCommit = 2, - OnRollback = 4 -}; - -extern "C" UINT __stdcall PSW_ShellExecute(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - PMSIHANDLE hView; - PMSIHANDLE hRecord; - CShellExecute oDeferredShellExecute; - CShellExecute oRollbackShellExecute; - CShellExecute oCommitShellExecute; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - // Ensure table PSW_ShellExecute exists. - hr = WcaTableExists(L"PSW_ShellExecute"); - ExitOnFailure(hr, "Failed to check if table exists 'PSW_ShellExecute'"); - ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_ShellExecute'. Have you authored 'PanelSw:ShellExecute' entries in WiX code?"); - - // Execute view - hr = WcaOpenExecuteView(ShellExecute_QUERY, &hView); - ExitOnFailure(hr, "Failed to execute SQL query '%ls'.", ShellExecute_QUERY); - - // Iterate records - while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) - { - ExitOnFailure(hr, "Failed to fetch record."); - - // Get fields - CWixString szId, szTarget, szArgs, szVerb, szWorkingDir, szCondition; - int nShow = 0; - int nFlags = ShellExecuteFlags::OnExecute; - int nWait = 0; - - hr = WcaGetRecordString(hRecord, ShellExecuteQuery::Id, (LPWSTR*)szId); - ExitOnFailure(hr, "Failed to get Id."); - hr = WcaGetRecordFormattedString(hRecord, ShellExecuteQuery::Target, (LPWSTR*)szTarget); - ExitOnFailure(hr, "Failed to get Target."); - hr = WcaGetRecordFormattedString(hRecord, ShellExecuteQuery::Args, (LPWSTR*)szArgs); - ExitOnFailure(hr, "Failed to get Args."); - hr = WcaGetRecordFormattedString(hRecord, ShellExecuteQuery::Verb, (LPWSTR*)szVerb); - ExitOnFailure(hr, "Failed to get Verb."); - hr = WcaGetRecordFormattedString(hRecord, ShellExecuteQuery::WorkingDir, (LPWSTR*)szWorkingDir); - ExitOnFailure(hr, "Failed to get WorkingDir."); - hr = WcaGetRecordInteger(hRecord, ShellExecuteQuery::Show, &nShow); - ExitOnFailure(hr, "Failed to get Show."); - hr = WcaGetRecordInteger(hRecord, ShellExecuteQuery::Wait, &nWait); - ExitOnFailure(hr, "Failed to get Wait."); - hr = WcaGetRecordInteger(hRecord, ShellExecuteQuery::Flags, &nFlags); - ExitOnFailure(hr, "Failed to get Flags."); - hr = WcaGetRecordString(hRecord, ShellExecuteQuery::Condition, (LPWSTR*)szCondition); - ExitOnFailure(hr, "Failed to get Condition."); - - // Test condition - MSICONDITION condRes = ::MsiEvaluateConditionW(hInstall, szCondition); - switch (condRes) - { - case MSICONDITION::MSICONDITION_NONE: - case MSICONDITION::MSICONDITION_TRUE: - WcaLog(LOGMSG_STANDARD, "Condition evaluated to true / none."); - break; - - case MSICONDITION::MSICONDITION_FALSE: - WcaLog(LOGMSG_STANDARD, "Skipping. Condition evaluated to false"); - continue; - - case MSICONDITION::MSICONDITION_ERROR: - hr = E_FAIL; - ExitOnFailure(hr, "Bad Condition field"); - } - - if ((nFlags & ShellExecuteFlags::OnExecute) != 0) - { - hr = oDeferredShellExecute.AddShellExec(szTarget, szArgs, szVerb, szWorkingDir, nShow, nWait != 0); - ExitOnFailure(hr, "Failed creating custom action data for deferred action."); - } - if ((nFlags & ShellExecuteFlags::OnCommit) != 0) - { - hr = oCommitShellExecute.AddShellExec(szTarget, szArgs, szVerb, szWorkingDir, nShow, nWait != 0); - ExitOnFailure(hr, "Failed creating custom action data for deferred action."); - } - if ((nFlags & ShellExecuteFlags::OnRollback) != 0) - { - hr = oRollbackShellExecute.AddShellExec(szTarget, szArgs, szVerb, szWorkingDir, nShow, nWait != 0); - ExitOnFailure(hr, "Failed creating custom action data for deferred action."); - } - } - - // Schedule actions. - hr = oRollbackShellExecute.DoDeferredAction(L"ShellExecute_rollback"); - ExitOnFailure(hr, "Failed scheduling rollback action."); - - hr = oDeferredShellExecute.DoDeferredAction(L"ShellExecute_deferred"); - ExitOnFailure(hr, "Failed scheduling deferred action."); - - hr = oCommitShellExecute.DoDeferredAction(L"ShellExecute_commit"); - ExitOnFailure(hr, "Failed scheduling commit action."); - -LExit: - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - -HRESULT CShellExecute::AddShellExec(LPCWSTR szTarget, LPCWSTR szArgs, LPCWSTR szVerb, LPCWSTR szWorkingDir, int nShow, bool bWait) -{ - HRESULT hr = S_OK; - ::com::panelsw::ca::Command *pCmd = nullptr; - ShellExecDetails *pDetails = nullptr; - ::std::string *pAny = nullptr; - bool bRes = true; - - hr = AddCommand("CShellExecute", &pCmd); - ExitOnFailure(hr, "Failed to add command"); - - pDetails = new ShellExecDetails(); - ExitOnNull(pDetails, hr, E_FAIL, "Failed allocating details"); - - pDetails->set_target(szTarget, WSTR_BYTE_SIZE(szTarget)); - pDetails->set_args(szArgs, WSTR_BYTE_SIZE(szArgs)); - pDetails->set_verb(szVerb, WSTR_BYTE_SIZE(szVerb)); - pDetails->set_workdir(szWorkingDir, WSTR_BYTE_SIZE(szWorkingDir)); - - pDetails->set_wait(bWait); - pDetails->set_show(nShow); - - pAny = pCmd->mutable_details(); - ExitOnNull(pAny, hr, E_FAIL, "Failed allocating any"); - - bRes = pDetails->SerializeToString(pAny); - ExitOnNull(bRes, hr, E_FAIL, "Failed serializing command details"); - -LExit: - return hr; -} - -HRESULT CShellExecute::DeferredExecute(const ::std::string& command) -{ - HRESULT hr = S_OK; - BOOL bRes = TRUE; - ShellExecDetails details; - LPCWSTR szTarget = nullptr; - LPCWSTR szArgs = nullptr; - LPCWSTR szVerb = nullptr; - LPCWSTR szWorkingDir = nullptr; - int nShow; - bool bWait; - - bRes = details.ParseFromString(command); - ExitOnNull(bRes, hr, E_INVALIDARG, "Failed unpacking ShellExecDetails"); - - szTarget = (LPCWSTR)(LPVOID)details.target().data(); - szArgs = (LPCWSTR)(LPVOID)details.args().data(); - szVerb = (LPCWSTR)(LPVOID)details.verb().data(); - nShow = details.show(); - bWait = details.wait(); - - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "ShellExecute: Target='%ls' Args='%ls' Verb='%ls' WorkingDir='%ls' Show=%i Wait=%i", szTarget, szArgs, szVerb, szWorkingDir, nShow, bWait); - - hr = Execute(szTarget, szArgs, szVerb, szWorkingDir, nShow, bWait); - ExitOnFailure(hr, "Failed to execute \"%ls\" %ls", szTarget, szArgs); - -LExit: - return hr; -} - -HRESULT CShellExecute::Execute(LPCWSTR szTarget, LPCWSTR szArgs, LPCWSTR szVerb, LPCWSTR szWorkingDir, int nShow, bool bWait) -{ - HRESULT hr = S_OK; - SHELLEXECUTEINFO shExecInfo = {}; - PMSIHANDLE hRecord; - - // Notify progress data - hRecord = ::MsiCreateRecord(4); - WcaSetRecordString(hRecord, 1, szTarget); - WcaSetRecordString(hRecord, 2, szArgs); - WcaSetRecordString(hRecord, 3, szVerb); - WcaSetRecordString(hRecord, 4, szWorkingDir); - WcaProcessMessage(INSTALLMESSAGE::INSTALLMESSAGE_ACTIONDATA, hRecord); - - - shExecInfo.cbSize = sizeof(shExecInfo); - shExecInfo.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI; - if (bWait) - { - shExecInfo.fMask |= SEE_MASK_NOCLOSEPROCESS; - } - - shExecInfo.lpVerb = szVerb; - shExecInfo.lpFile = szTarget; - shExecInfo.lpParameters = szArgs; - shExecInfo.lpDirectory = szWorkingDir; - shExecInfo.nShow = nShow; - - if (!::ShellExecuteEx(&shExecInfo)) - { - switch (reinterpret_cast(shExecInfo.hInstApp)) - { - case SE_ERR_FNF: - hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - break; - case SE_ERR_PNF: - hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); - break; - case ERROR_BAD_FORMAT: - hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT); - break; - case SE_ERR_ASSOCINCOMPLETE: - case SE_ERR_NOASSOC: - hr = HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION); - break; - case SE_ERR_DDEBUSY: __fallthrough; - case SE_ERR_DDEFAIL: __fallthrough; - case SE_ERR_DDETIMEOUT: - hr = HRESULT_FROM_WIN32(ERROR_DDE_FAIL); - break; - case SE_ERR_DLLNOTFOUND: - hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND); - break; - case SE_ERR_OOM: - hr = E_OUTOFMEMORY; - break; - case SE_ERR_ACCESSDENIED: - hr = E_ACCESSDENIED; - break; - default: - hr = E_FAIL; - } - ExitOnFailure(hr, "ShellExecEx failed with return code %d", reinterpret_cast(shExecInfo.hInstApp)); - } - - if (bWait) - { - ::WaitForSingleObject(shExecInfo.hProcess, INFINITE); - ::CloseHandle(shExecInfo.hProcess); - shExecInfo.hProcess = NULL; - } - -LExit: - - return hr; -} +#include "pch.h" +#include "ShellExecute.h" +#include +#include "shellExecDetails.pb.h" +using namespace ::com::panelsw::ca; +using namespace google::protobuf; +#pragma comment (lib, "Shell32.lib") + + +#define ShellExecute_QUERY L"SELECT `Id`, `Target`, `Args`, `Verb`, `WorkingDir`, `Show`, `Wait`, `Flags`, `Condition` FROM `PSW_ShellExecute`" +enum ShellExecuteQuery { Id=1, Target=2, Args=3, Verb=4, WorkingDir=5, Show=6, Wait=7, Flags=8, Condition=9 }; + +enum ShellExecuteFlags +{ + None = 0, + OnExecute = 1, + OnCommit = 2, + OnRollback = 4 +}; + +extern "C" UINT __stdcall PSW_ShellExecute(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + PMSIHANDLE hView; + PMSIHANDLE hRecord; + CShellExecute oDeferredShellExecute; + CShellExecute oRollbackShellExecute; + CShellExecute oCommitShellExecute; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + // Ensure table PSW_ShellExecute exists. + hr = WcaTableExists(L"PSW_ShellExecute"); + ExitOnFailure(hr, "Failed to check if table exists 'PSW_ShellExecute'"); + ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_ShellExecute'. Have you authored 'PanelSw:ShellExecute' entries in WiX code?"); + + // Execute view + hr = WcaOpenExecuteView(ShellExecute_QUERY, &hView); + ExitOnFailure(hr, "Failed to execute SQL query '%ls'.", ShellExecute_QUERY); + + // Iterate records + while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) + { + ExitOnFailure(hr, "Failed to fetch record."); + + // Get fields + CWixString szId, szTarget, szArgs, szVerb, szWorkingDir, szCondition; + int nShow = 0; + int nFlags = ShellExecuteFlags::OnExecute; + int nWait = 0; + + hr = WcaGetRecordString(hRecord, ShellExecuteQuery::Id, (LPWSTR*)szId); + ExitOnFailure(hr, "Failed to get Id."); + hr = WcaGetRecordFormattedString(hRecord, ShellExecuteQuery::Target, (LPWSTR*)szTarget); + ExitOnFailure(hr, "Failed to get Target."); + hr = WcaGetRecordFormattedString(hRecord, ShellExecuteQuery::Args, (LPWSTR*)szArgs); + ExitOnFailure(hr, "Failed to get Args."); + hr = WcaGetRecordFormattedString(hRecord, ShellExecuteQuery::Verb, (LPWSTR*)szVerb); + ExitOnFailure(hr, "Failed to get Verb."); + hr = WcaGetRecordFormattedString(hRecord, ShellExecuteQuery::WorkingDir, (LPWSTR*)szWorkingDir); + ExitOnFailure(hr, "Failed to get WorkingDir."); + hr = WcaGetRecordInteger(hRecord, ShellExecuteQuery::Show, &nShow); + ExitOnFailure(hr, "Failed to get Show."); + hr = WcaGetRecordInteger(hRecord, ShellExecuteQuery::Wait, &nWait); + ExitOnFailure(hr, "Failed to get Wait."); + hr = WcaGetRecordInteger(hRecord, ShellExecuteQuery::Flags, &nFlags); + ExitOnFailure(hr, "Failed to get Flags."); + hr = WcaGetRecordString(hRecord, ShellExecuteQuery::Condition, (LPWSTR*)szCondition); + ExitOnFailure(hr, "Failed to get Condition."); + + // Test condition + MSICONDITION condRes = ::MsiEvaluateConditionW(hInstall, szCondition); + switch (condRes) + { + case MSICONDITION::MSICONDITION_NONE: + case MSICONDITION::MSICONDITION_TRUE: + WcaLog(LOGMSG_STANDARD, "Condition evaluated to true / none."); + break; + + case MSICONDITION::MSICONDITION_FALSE: + WcaLog(LOGMSG_STANDARD, "Skipping. Condition evaluated to false"); + continue; + + case MSICONDITION::MSICONDITION_ERROR: + hr = E_FAIL; + ExitOnFailure(hr, "Bad Condition field"); + } + + if ((nFlags & ShellExecuteFlags::OnExecute) != 0) + { + hr = oDeferredShellExecute.AddShellExec(szTarget, szArgs, szVerb, szWorkingDir, nShow, nWait != 0); + ExitOnFailure(hr, "Failed creating custom action data for deferred action."); + } + if ((nFlags & ShellExecuteFlags::OnCommit) != 0) + { + hr = oCommitShellExecute.AddShellExec(szTarget, szArgs, szVerb, szWorkingDir, nShow, nWait != 0); + ExitOnFailure(hr, "Failed creating custom action data for deferred action."); + } + if ((nFlags & ShellExecuteFlags::OnRollback) != 0) + { + hr = oRollbackShellExecute.AddShellExec(szTarget, szArgs, szVerb, szWorkingDir, nShow, nWait != 0); + ExitOnFailure(hr, "Failed creating custom action data for deferred action."); + } + } + + // Schedule actions. + hr = oRollbackShellExecute.DoDeferredAction(L"ShellExecute_rollback"); + ExitOnFailure(hr, "Failed scheduling rollback action."); + + hr = oDeferredShellExecute.DoDeferredAction(L"ShellExecute_deferred"); + ExitOnFailure(hr, "Failed scheduling deferred action."); + + hr = oCommitShellExecute.DoDeferredAction(L"ShellExecute_commit"); + ExitOnFailure(hr, "Failed scheduling commit action."); + +LExit: + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +HRESULT CShellExecute::AddShellExec(LPCWSTR szTarget, LPCWSTR szArgs, LPCWSTR szVerb, LPCWSTR szWorkingDir, int nShow, bool bWait) +{ + HRESULT hr = S_OK; + ::com::panelsw::ca::Command *pCmd = nullptr; + ShellExecDetails *pDetails = nullptr; + ::std::string *pAny = nullptr; + bool bRes = true; + + hr = AddCommand("CShellExecute", &pCmd); + ExitOnFailure(hr, "Failed to add command"); + + pDetails = new ShellExecDetails(); + ExitOnNull(pDetails, hr, E_FAIL, "Failed allocating details"); + + pDetails->set_target(szTarget, WSTR_BYTE_SIZE(szTarget)); + pDetails->set_args(szArgs, WSTR_BYTE_SIZE(szArgs)); + pDetails->set_verb(szVerb, WSTR_BYTE_SIZE(szVerb)); + pDetails->set_workdir(szWorkingDir, WSTR_BYTE_SIZE(szWorkingDir)); + + pDetails->set_wait(bWait); + pDetails->set_show(nShow); + + pAny = pCmd->mutable_details(); + ExitOnNull(pAny, hr, E_FAIL, "Failed allocating any"); + + bRes = pDetails->SerializeToString(pAny); + ExitOnNull(bRes, hr, E_FAIL, "Failed serializing command details"); + +LExit: + return hr; +} + +HRESULT CShellExecute::DeferredExecute(const ::std::string& command) +{ + HRESULT hr = S_OK; + BOOL bRes = TRUE; + ShellExecDetails details; + LPCWSTR szTarget = nullptr; + LPCWSTR szArgs = nullptr; + LPCWSTR szVerb = nullptr; + LPCWSTR szWorkingDir = nullptr; + int nShow; + bool bWait; + + bRes = details.ParseFromString(command); + ExitOnNull(bRes, hr, E_INVALIDARG, "Failed unpacking ShellExecDetails"); + + szTarget = (LPCWSTR)(LPVOID)details.target().data(); + szArgs = (LPCWSTR)(LPVOID)details.args().data(); + szVerb = (LPCWSTR)(LPVOID)details.verb().data(); + nShow = details.show(); + bWait = details.wait(); + + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "ShellExecute: Target='%ls' Args='%ls' Verb='%ls' WorkingDir='%ls' Show=%i Wait=%i", szTarget, szArgs, szVerb, szWorkingDir, nShow, bWait); + + hr = Execute(szTarget, szArgs, szVerb, szWorkingDir, nShow, bWait); + ExitOnFailure(hr, "Failed to execute \"%ls\" %ls", szTarget, szArgs); + +LExit: + return hr; +} + +HRESULT CShellExecute::Execute(LPCWSTR szTarget, LPCWSTR szArgs, LPCWSTR szVerb, LPCWSTR szWorkingDir, int nShow, bool bWait) +{ + HRESULT hr = S_OK; + SHELLEXECUTEINFO shExecInfo = {}; + PMSIHANDLE hRecord; + + // Notify progress data + hRecord = ::MsiCreateRecord(4); + WcaSetRecordString(hRecord, 1, szTarget); + WcaSetRecordString(hRecord, 2, szArgs); + WcaSetRecordString(hRecord, 3, szVerb); + WcaSetRecordString(hRecord, 4, szWorkingDir); + WcaProcessMessage(INSTALLMESSAGE::INSTALLMESSAGE_ACTIONDATA, hRecord); + + + shExecInfo.cbSize = sizeof(shExecInfo); + shExecInfo.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI; + if (bWait) + { + shExecInfo.fMask |= SEE_MASK_NOCLOSEPROCESS; + } + + shExecInfo.lpVerb = szVerb; + shExecInfo.lpFile = szTarget; + shExecInfo.lpParameters = szArgs; + shExecInfo.lpDirectory = szWorkingDir; + shExecInfo.nShow = nShow; + + if (!::ShellExecuteEx(&shExecInfo)) + { + switch (reinterpret_cast(shExecInfo.hInstApp)) + { + case SE_ERR_FNF: + hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + break; + case SE_ERR_PNF: + hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); + break; + case ERROR_BAD_FORMAT: + hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT); + break; + case SE_ERR_ASSOCINCOMPLETE: + case SE_ERR_NOASSOC: + hr = HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION); + break; + case SE_ERR_DDEBUSY: __fallthrough; + case SE_ERR_DDEFAIL: __fallthrough; + case SE_ERR_DDETIMEOUT: + hr = HRESULT_FROM_WIN32(ERROR_DDE_FAIL); + break; + case SE_ERR_DLLNOTFOUND: + hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND); + break; + case SE_ERR_OOM: + hr = E_OUTOFMEMORY; + break; + case SE_ERR_ACCESSDENIED: + hr = E_ACCESSDENIED; + break; + default: + hr = E_FAIL; + } + ExitOnFailure(hr, "ShellExecEx failed with return code %d", reinterpret_cast(shExecInfo.hInstApp)); + } + + if (bWait) + { + ::WaitForSingleObject(shExecInfo.hProcess, INFINITE); + ::CloseHandle(shExecInfo.hProcess); + shExecInfo.hProcess = NULL; + } + +LExit: + + return hr; +} diff --git a/PanelSwCustomActions/ShellExecute.h b/src/PanelSwCustomActions/ShellExecute.h similarity index 96% rename from PanelSwCustomActions/ShellExecute.h rename to src/PanelSwCustomActions/ShellExecute.h index 63b150e2..31350ae4 100644 --- a/PanelSwCustomActions/ShellExecute.h +++ b/src/PanelSwCustomActions/ShellExecute.h @@ -1,19 +1,19 @@ -#pragma once -#include "../CaCommon/DeferredActionBase.h" - -class CShellExecute : - public CDeferredActionBase -{ -public: - - CShellExecute() : CDeferredActionBase("ShellExec") { } - - HRESULT AddShellExec(LPCWSTR szTarget, LPCWSTR szArgs, LPCWSTR szVerb, LPCWSTR szWorkingDir, int nShow, bool bWait); - -protected: - - HRESULT DeferredExecute(const ::std::string& command) override; - -private: - HRESULT Execute(LPCWSTR szTarget, LPCWSTR szArgs, LPCWSTR szVerb, LPCWSTR szWorkingDir, int nShow, bool bWait); +#pragma once +#include "../CaCommon/DeferredActionBase.h" + +class CShellExecute : + public CDeferredActionBase +{ +public: + + CShellExecute() : CDeferredActionBase("ShellExec") { } + + HRESULT AddShellExec(LPCWSTR szTarget, LPCWSTR szArgs, LPCWSTR szVerb, LPCWSTR szWorkingDir, int nShow, bool bWait); + +protected: + + HRESULT DeferredExecute(const ::std::string& command) override; + +private: + HRESULT Execute(LPCWSTR szTarget, LPCWSTR szArgs, LPCWSTR szVerb, LPCWSTR szWorkingDir, int nShow, bool bWait); }; \ No newline at end of file diff --git a/PanelSwCustomActions/SqlScript.cpp b/src/PanelSwCustomActions/SqlScript.cpp similarity index 100% rename from PanelSwCustomActions/SqlScript.cpp rename to src/PanelSwCustomActions/SqlScript.cpp diff --git a/PanelSwCustomActions/SqlScript.h b/src/PanelSwCustomActions/SqlScript.h similarity index 100% rename from PanelSwCustomActions/SqlScript.h rename to src/PanelSwCustomActions/SqlScript.h diff --git a/PanelSwCustomActions/SqlSearch.cpp b/src/PanelSwCustomActions/SqlSearch.cpp similarity index 97% rename from PanelSwCustomActions/SqlSearch.cpp rename to src/PanelSwCustomActions/SqlSearch.cpp index a2ff52d2..1ae70875 100644 --- a/PanelSwCustomActions/SqlSearch.cpp +++ b/src/PanelSwCustomActions/SqlSearch.cpp @@ -1,144 +1,144 @@ -#include "pch.h" -#include "../CaCommon/SqlConnection.h" -#include "../CaCommon/SqlQuery.h" -#include "errorHandling.pb.h" -using namespace ::com::panelsw::ca; -#include "SqlScript.h" - -static HRESULT ExecuteOne(LPCWSTR szConnectionString, LPCWSTR szServer, LPCWSTR szInstance, int nPort, LPCWSTR szDatabase, LPCWSTR szUsername, LPCWSTR szPassword, bool bEncrypted, ErrorHandling errorHandling, LPCWSTR szPropertyName, LPCWSTR szQuery); - -extern "C" UINT __stdcall SqlSearch(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - PMSIHANDLE hView; - PMSIHANDLE hRecord; - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - hr = WcaTableExists(L"PSW_SqlSearch"); - ExitOnFailure(hr, "Failed to check if table exists 'PSW_SqlSearch'"); - ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_SqlSearch'. Have you authored 'PanelSw:SqlSearch' entries in WiX code?"); - - // Execute view - hr = WcaOpenExecuteView(L"SELECT `Property_`, `Server`, `Instance`, `Database`, `Username`, `Password`, `Query`, `Condition`, `Port`, `Encrypted`, `ErrorHandling`, `ConnectionString` FROM `PSW_SqlSearch` ORDER BY `Order`", &hView); - ExitOnFailure(hr, "Failed to execute SQL query on 'PSW_SqlSearch'."); - - // Iterate records - while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) - { - ExitOnFailure(hr, "Failed to fetch record."); - - // Get fields - CWixString szProperty; - CWixString szConnectionString; - CWixString szServer; - CWixString szInstance; - CWixString szDatabase; - CWixString szUsername; - CWixString szPassword; - CWixString szQuery; - CWixString szCondition; - CWixString szResult; - CWixString szEncrypted; - int nPort = 0; - int bEncrypted = 0; - ErrorHandling nErrorHandling = ErrorHandling::fail; - - hr = WcaGetRecordString(hRecord, 1, (LPWSTR*)szProperty); - ExitOnFailure(hr, "Failed to get Property_."); - hr = WcaGetRecordFormattedString(hRecord, 2, (LPWSTR*)szServer); - ExitOnFailure(hr, "Failed to get Server."); - hr = WcaGetRecordFormattedString(hRecord, 3, (LPWSTR*)szInstance); - ExitOnFailure(hr, "Failed to get Instance."); - hr = WcaGetRecordFormattedString(hRecord, 4, (LPWSTR*)szDatabase); - ExitOnFailure(hr, "Failed to get Database."); - hr = WcaGetRecordFormattedString(hRecord, 5, (LPWSTR*)szUsername); - ExitOnFailure(hr, "Failed to get Username."); - hr = WcaGetRecordFormattedString(hRecord, 6, (LPWSTR*)szPassword); - ExitOnFailure(hr, "Failed to get Password."); - hr = WcaGetRecordFormattedString(hRecord, 7, (LPWSTR*)szQuery); - ExitOnFailure(hr, "Failed to get Query."); - hr = WcaGetRecordString(hRecord, 8, (LPWSTR*)szCondition); - ExitOnFailure(hr, "Failed to get Condition."); - hr = WcaGetRecordFormattedInteger(hRecord, 9, &nPort); - ExitOnFailure(hr, "Failed to get Port."); - hr = WcaGetRecordFormattedString(hRecord, 10, (LPWSTR*)szEncrypted); - ExitOnFailure(hr, "Failed to get Encrypted."); - bEncrypted = (szEncrypted.EqualsIgnoreCase(L"true") || szEncrypted.EqualsIgnoreCase(L"yes") || szEncrypted.Equals(L"1")); - hr = WcaGetRecordInteger(hRecord, 11, (int*)&nErrorHandling); - ExitOnFailure(hr, "Failed to get ErrorHandling."); - hr = WcaGetRecordFormattedString(hRecord, 12, (LPWSTR*)szConnectionString); - ExitOnFailure(hr, "Failed to get ConnectionString."); - - if (!szCondition.IsNullOrEmpty()) - { - MSICONDITION condRes = MSICONDITION::MSICONDITION_NONE; - - condRes = ::MsiEvaluateCondition(hInstall, szCondition); - ExitOnNullWithLastError((condRes != MSICONDITION::MSICONDITION_ERROR), hr, "Failed evaluating condition '%ls'", (LPCWSTR)szCondition); - - hr = (condRes == MSICONDITION::MSICONDITION_FALSE) ? S_FALSE : S_OK; - WcaLog(LOGMSG_STANDARD, "Condition '%ls' evaluated to %i", (LPCWSTR)szCondition, (1 - (int)hr)); - if (hr == S_FALSE) - { - continue; - } - } - - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Executing SQL query '%ls'. Will place results in property '%ls'", (LPCWSTR)szQuery, (LPCWSTR)szProperty); - - hr = ExecuteOne((LPCWSTR)szConnectionString, (LPCWSTR)szServer, (LPCWSTR)szInstance, nPort, (LPCWSTR)szDatabase, (LPCWSTR)szUsername, (LPCWSTR)szPassword, bEncrypted, nErrorHandling, szProperty, szQuery); - ExitOnFailure(hr, "Failed executing SQL search"); - } - hr = S_OK; - -LExit: - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - -static HRESULT ExecuteOne(LPCWSTR szConnectionString, LPCWSTR szServer, LPCWSTR szInstance, int nPort, LPCWSTR szDatabase, LPCWSTR szUsername, LPCWSTR szPassword, bool bEncrypted, ErrorHandling errorHandling, LPCWSTR szPropertyName, LPCWSTR szQuery) -{ - HRESULT hr = S_OK; - CSqlConnection sqlConn; - CSqlQuery sqlQuery; - CWixString szResult; - CWixString szError; - CErrorPrompter errorPrompter(PSW_MSI_MESSAGES::PSW_MSI_MESSAGES_SQL_SEARCH_ERROR); - errorPrompter.SetErrorHandling((PSW_ERROR_HANDLING)errorHandling); - -LRetry: - if (szConnectionString && *szConnectionString) - { - hr = sqlConn.Connect(szConnectionString, (LPWSTR*)szError); - } - else - { - hr = sqlConn.Connect(nullptr, szServer, szInstance, nPort, szDatabase, szUsername, szPassword, bEncrypted, (LPWSTR*)szError); - } - if (SUCCEEDED(hr)) - { - hr = sqlQuery.ExecuteQuery(sqlConn, szQuery, (LPWSTR*)szResult, (LPWSTR*)szError); - } - - if (FAILED(hr)) - { - WcaLogError(hr, "Failed executing SQL query: %ls", (LPCWSTR)szError); - hr = errorPrompter.Prompt(szQuery, (LPCWSTR)szError); - if (hr == E_RETRY) - { - hr = S_OK; - goto LRetry; - } - } - ExitOnFailure(hr, "Failed excuting SQL search"); - - hr = WcaSetProperty(szPropertyName, szResult.IsNullOrEmpty() ? L"" : (LPCWSTR)szResult); - ExitOnFailure(hr, "Failed setting property '%ls'", szPropertyName); - -LExit: - return hr; -} +#include "pch.h" +#include "../CaCommon/SqlConnection.h" +#include "../CaCommon/SqlQuery.h" +#include "errorHandling.pb.h" +using namespace ::com::panelsw::ca; +#include "SqlScript.h" + +static HRESULT ExecuteOne(LPCWSTR szConnectionString, LPCWSTR szServer, LPCWSTR szInstance, int nPort, LPCWSTR szDatabase, LPCWSTR szUsername, LPCWSTR szPassword, bool bEncrypted, ErrorHandling errorHandling, LPCWSTR szPropertyName, LPCWSTR szQuery); + +extern "C" UINT __stdcall SqlSearch(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + PMSIHANDLE hView; + PMSIHANDLE hRecord; + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + hr = WcaTableExists(L"PSW_SqlSearch"); + ExitOnFailure(hr, "Failed to check if table exists 'PSW_SqlSearch'"); + ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_SqlSearch'. Have you authored 'PanelSw:SqlSearch' entries in WiX code?"); + + // Execute view + hr = WcaOpenExecuteView(L"SELECT `Property_`, `Server`, `Instance`, `Database`, `Username`, `Password`, `Query`, `Condition`, `Port`, `Encrypted`, `ErrorHandling`, `ConnectionString` FROM `PSW_SqlSearch` ORDER BY `Order`", &hView); + ExitOnFailure(hr, "Failed to execute SQL query on 'PSW_SqlSearch'."); + + // Iterate records + while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) + { + ExitOnFailure(hr, "Failed to fetch record."); + + // Get fields + CWixString szProperty; + CWixString szConnectionString; + CWixString szServer; + CWixString szInstance; + CWixString szDatabase; + CWixString szUsername; + CWixString szPassword; + CWixString szQuery; + CWixString szCondition; + CWixString szResult; + CWixString szEncrypted; + int nPort = 0; + int bEncrypted = 0; + ErrorHandling nErrorHandling = ErrorHandling::fail; + + hr = WcaGetRecordString(hRecord, 1, (LPWSTR*)szProperty); + ExitOnFailure(hr, "Failed to get Property_."); + hr = WcaGetRecordFormattedString(hRecord, 2, (LPWSTR*)szServer); + ExitOnFailure(hr, "Failed to get Server."); + hr = WcaGetRecordFormattedString(hRecord, 3, (LPWSTR*)szInstance); + ExitOnFailure(hr, "Failed to get Instance."); + hr = WcaGetRecordFormattedString(hRecord, 4, (LPWSTR*)szDatabase); + ExitOnFailure(hr, "Failed to get Database."); + hr = WcaGetRecordFormattedString(hRecord, 5, (LPWSTR*)szUsername); + ExitOnFailure(hr, "Failed to get Username."); + hr = WcaGetRecordFormattedString(hRecord, 6, (LPWSTR*)szPassword); + ExitOnFailure(hr, "Failed to get Password."); + hr = WcaGetRecordFormattedString(hRecord, 7, (LPWSTR*)szQuery); + ExitOnFailure(hr, "Failed to get Query."); + hr = WcaGetRecordString(hRecord, 8, (LPWSTR*)szCondition); + ExitOnFailure(hr, "Failed to get Condition."); + hr = WcaGetRecordFormattedInteger(hRecord, 9, &nPort); + ExitOnFailure(hr, "Failed to get Port."); + hr = WcaGetRecordFormattedString(hRecord, 10, (LPWSTR*)szEncrypted); + ExitOnFailure(hr, "Failed to get Encrypted."); + bEncrypted = (szEncrypted.EqualsIgnoreCase(L"true") || szEncrypted.EqualsIgnoreCase(L"yes") || szEncrypted.Equals(L"1")); + hr = WcaGetRecordInteger(hRecord, 11, (int*)&nErrorHandling); + ExitOnFailure(hr, "Failed to get ErrorHandling."); + hr = WcaGetRecordFormattedString(hRecord, 12, (LPWSTR*)szConnectionString); + ExitOnFailure(hr, "Failed to get ConnectionString."); + + if (!szCondition.IsNullOrEmpty()) + { + MSICONDITION condRes = MSICONDITION::MSICONDITION_NONE; + + condRes = ::MsiEvaluateCondition(hInstall, szCondition); + ExitOnNullWithLastError((condRes != MSICONDITION::MSICONDITION_ERROR), hr, "Failed evaluating condition '%ls'", (LPCWSTR)szCondition); + + hr = (condRes == MSICONDITION::MSICONDITION_FALSE) ? S_FALSE : S_OK; + WcaLog(LOGMSG_STANDARD, "Condition '%ls' evaluated to %i", (LPCWSTR)szCondition, (1 - (int)hr)); + if (hr == S_FALSE) + { + continue; + } + } + + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Executing SQL query '%ls'. Will place results in property '%ls'", (LPCWSTR)szQuery, (LPCWSTR)szProperty); + + hr = ExecuteOne((LPCWSTR)szConnectionString, (LPCWSTR)szServer, (LPCWSTR)szInstance, nPort, (LPCWSTR)szDatabase, (LPCWSTR)szUsername, (LPCWSTR)szPassword, bEncrypted, nErrorHandling, szProperty, szQuery); + ExitOnFailure(hr, "Failed executing SQL search"); + } + hr = S_OK; + +LExit: + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +static HRESULT ExecuteOne(LPCWSTR szConnectionString, LPCWSTR szServer, LPCWSTR szInstance, int nPort, LPCWSTR szDatabase, LPCWSTR szUsername, LPCWSTR szPassword, bool bEncrypted, ErrorHandling errorHandling, LPCWSTR szPropertyName, LPCWSTR szQuery) +{ + HRESULT hr = S_OK; + CSqlConnection sqlConn; + CSqlQuery sqlQuery; + CWixString szResult; + CWixString szError; + CErrorPrompter errorPrompter(PSW_MSI_MESSAGES::PSW_MSI_MESSAGES_SQL_SEARCH_ERROR); + errorPrompter.SetErrorHandling((PSW_ERROR_HANDLING)errorHandling); + +LRetry: + if (szConnectionString && *szConnectionString) + { + hr = sqlConn.Connect(szConnectionString, (LPWSTR*)szError); + } + else + { + hr = sqlConn.Connect(nullptr, szServer, szInstance, nPort, szDatabase, szUsername, szPassword, bEncrypted, (LPWSTR*)szError); + } + if (SUCCEEDED(hr)) + { + hr = sqlQuery.ExecuteQuery(sqlConn, szQuery, (LPWSTR*)szResult, (LPWSTR*)szError); + } + + if (FAILED(hr)) + { + WcaLogError(hr, "Failed executing SQL query: %ls", (LPCWSTR)szError); + hr = errorPrompter.Prompt(szQuery, (LPCWSTR)szError); + if (hr == E_RETRY) + { + hr = S_OK; + goto LRetry; + } + } + ExitOnFailure(hr, "Failed excuting SQL search"); + + hr = WcaSetProperty(szPropertyName, szResult.IsNullOrEmpty() ? L"" : (LPCWSTR)szResult); + ExitOnFailure(hr, "Failed setting property '%ls'", szPropertyName); + +LExit: + return hr; +} diff --git a/PanelSwCustomActions/StringOperations.cpp b/src/PanelSwCustomActions/StringOperations.cpp similarity index 96% rename from PanelSwCustomActions/StringOperations.cpp rename to src/PanelSwCustomActions/StringOperations.cpp index 654668f1..a68406d3 100644 --- a/PanelSwCustomActions/StringOperations.cpp +++ b/src/PanelSwCustomActions/StringOperations.cpp @@ -1,219 +1,219 @@ -#include "pch.h" - -#define SplitProp L"PROPERTY_TO_SPLIT" -#define SplitTokenProp L"STRING_SPLIT_TOKEN" - -extern "C" UINT __stdcall SplitString(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - BOOL bRes = TRUE; - CWixString szFullString; - CWixString szPropName; - CWixString szDstPropName; - CWixString szToken; - LPCWSTR szCurrValue = nullptr; - size_t i = 0; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - // Get property-to-split name - hr = WcaGetProperty(SplitProp, (LPWSTR*)szPropName); - ExitOnFailure(hr, "Failed getting %ls", SplitProp); - if (szPropName.IsNullOrEmpty()) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No property name to split..."); - ExitFunction(); - } - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will split property '%ls'", (LPCWSTR)szPropName); - - // Get string-to-split - hr = WcaGetProperty((LPCWSTR)szPropName, (LPWSTR*)szFullString); - ExitOnFailure(hr, "Failed getting %ls", (LPCWSTR)szPropName); - if (szFullString.IsNullOrEmpty()) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No string to split..."); - ExitFunction(); - } - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Will split string '%ls'", (LPCWSTR)szFullString); - - // Get token-to-split-by - hr = WcaGetProperty(SplitTokenProp, (LPWSTR*)szToken); - ExitOnFailure(hr, "Failed getting %ls", SplitTokenProp); - if (szToken.IsNullOrEmpty()) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No token to split by..."); - ExitFunction(); - } - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Will split string '%ls' by token '%ls'", (LPCWSTR)szFullString, (LPCWSTR)szToken); - - hr = szDstPropName.Allocate(szPropName.Capacity() + 20); - ExitOnFailure(hr, "Failed allocating memory"); - - for (hr = szFullString.Tokenize((LPCWSTR)szToken, &szCurrValue); - (SUCCEEDED(hr) && szCurrValue); - ++i, hr = szFullString.NextToken((LPCWSTR)szToken, &szCurrValue)) - { - hr = szDstPropName.Format(L"%ls_%Iu", (LPCWSTR)szPropName, i); - ExitOnFailure(hr, "Failed formatting string"); - - hr = WcaSetProperty((LPCWSTR)szDstPropName, szCurrValue); - ExitOnFailure(hr, "Failed setting property '%ls'", (LPCWSTR)szDstPropName); - } - - if (hr == E_NOMOREITEMS) - { - hr = S_OK; - } - -LExit: - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - -#undef SplitProp -#undef SplitTokenProp - -#define TrimProp L"PROPERTY_TO_TRIM" - -extern "C" UINT __stdcall TrimString(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - BOOL bRes = TRUE; - CWixString szPropName; - CWixString szFullString; - LPCWSTR pFirst = nullptr; - size_t i = 0; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - // Get property-to-trim name - hr = WcaGetProperty(TrimProp, (LPWSTR*)szPropName); - ExitOnFailure(hr, "Failed getting %ls", TrimProp); - if (szPropName.IsNullOrEmpty()) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No property name to trim..."); - ExitFunction(); - } - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will trim property '%ls'", (LPCWSTR)szPropName); - - // Get string-to-trim - hr = WcaGetProperty((LPCWSTR)szPropName, (LPWSTR*)szFullString); - ExitOnFailure(hr, "Failed getting %ls", (LPCWSTR)szPropName); - if (szFullString.IsNullOrEmpty()) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No string to trim..."); - ExitFunction(); - } - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Will trim string '%ls'", (LPCWSTR)szFullString); - - // Trim right (i is unsigned, so after 0 it will be MAX_SIZE) - for (i = szFullString.StrLen() - 1; i < szFullString.StrLen(); --i) - { - switch (((LPCWSTR)szFullString)[i]) - { - case L' ': - case L'\r': - case L'\n': - case L'\t': - case L'\v': - ((LPWSTR)szFullString)[i] = NULL; - continue; - - default: - break; - } - break; - } - - // Trim left - for (i = 0; i < szFullString.StrLen(); ++i) - { - switch (((LPCWSTR)szFullString)[i]) - { - case L' ': - case L'\r': - case L'\n': - case L'\t': - case L'\v': - continue; - - default: - break; - } - break; - } - - if (i == szFullString.StrLen()) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "%ls is all white-spaces", szPropName); - - hr = WcaSetProperty(szPropName, L""); - ExitOnFailure(hr, "Failed setting %ls", (LPCWSTR)szPropName); - } - - pFirst = i + (LPCWSTR)szFullString; - hr = WcaSetProperty(szPropName, pFirst); - ExitOnFailure(hr, "Failed setting %ls", (LPCWSTR)szPropName); - -LExit: - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - -extern "C" UINT __stdcall ToLowerCase(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - PMSIHANDLE hView; - PMSIHANDLE hRecord; - bool bIgnoreErrors = false; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - // Ensure table PSW_XmlSearch exists. - hr = WcaTableExists(L"PSW_ToLowerCase"); - ExitOnFailure(hr, "Failed to check if table exists 'PSW_ToLowerCase'"); - ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_ToLowerCase'. Have you authored 'PanelSw:ToLowerCase' entries in WiX code?"); - - // Execute view - hr = WcaOpenExecuteView(L"SELECT `Property_` FROM `PSW_ToLowerCase`", &hView); - ExitOnFailure(hr, "Failed to execute SQL query on 'PSW_ToLowerCase'."); - - // Iterate records - while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) - { - ExitOnFailure(hr, "Failed to fetch record."); - - // Get fields - CWixString szProperty, szValue; - - hr = WcaGetRecordString(hRecord, 1, (LPWSTR*)szProperty); - ExitOnFailure(hr, "Failed to get Property_."); - - hr = WcaGetProperty(szProperty, (LPWSTR*)szValue); - ExitOnFailure(hr, "Failed to get property '%ls' value.", (LPCWSTR)szProperty); - - StrStringToLower(szValue); - - hr = WcaSetProperty(szProperty, szValue); - ExitOnFailure(hr, "Failed setting property"); - } - hr = ERROR_SUCCESS; - -LExit: - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} +#include "pch.h" + +#define SplitProp L"PROPERTY_TO_SPLIT" +#define SplitTokenProp L"STRING_SPLIT_TOKEN" + +extern "C" UINT __stdcall SplitString(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + BOOL bRes = TRUE; + CWixString szFullString; + CWixString szPropName; + CWixString szDstPropName; + CWixString szToken; + LPCWSTR szCurrValue = nullptr; + size_t i = 0; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + // Get property-to-split name + hr = WcaGetProperty(SplitProp, (LPWSTR*)szPropName); + ExitOnFailure(hr, "Failed getting %ls", SplitProp); + if (szPropName.IsNullOrEmpty()) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No property name to split..."); + ExitFunction(); + } + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will split property '%ls'", (LPCWSTR)szPropName); + + // Get string-to-split + hr = WcaGetProperty((LPCWSTR)szPropName, (LPWSTR*)szFullString); + ExitOnFailure(hr, "Failed getting %ls", (LPCWSTR)szPropName); + if (szFullString.IsNullOrEmpty()) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No string to split..."); + ExitFunction(); + } + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Will split string '%ls'", (LPCWSTR)szFullString); + + // Get token-to-split-by + hr = WcaGetProperty(SplitTokenProp, (LPWSTR*)szToken); + ExitOnFailure(hr, "Failed getting %ls", SplitTokenProp); + if (szToken.IsNullOrEmpty()) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No token to split by..."); + ExitFunction(); + } + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Will split string '%ls' by token '%ls'", (LPCWSTR)szFullString, (LPCWSTR)szToken); + + hr = szDstPropName.Allocate(szPropName.Capacity() + 20); + ExitOnFailure(hr, "Failed allocating memory"); + + for (hr = szFullString.Tokenize((LPCWSTR)szToken, &szCurrValue); + (SUCCEEDED(hr) && szCurrValue); + ++i, hr = szFullString.NextToken((LPCWSTR)szToken, &szCurrValue)) + { + hr = szDstPropName.Format(L"%ls_%Iu", (LPCWSTR)szPropName, i); + ExitOnFailure(hr, "Failed formatting string"); + + hr = WcaSetProperty((LPCWSTR)szDstPropName, szCurrValue); + ExitOnFailure(hr, "Failed setting property '%ls'", (LPCWSTR)szDstPropName); + } + + if (hr == E_NOMOREITEMS) + { + hr = S_OK; + } + +LExit: + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +#undef SplitProp +#undef SplitTokenProp + +#define TrimProp L"PROPERTY_TO_TRIM" + +extern "C" UINT __stdcall TrimString(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + BOOL bRes = TRUE; + CWixString szPropName; + CWixString szFullString; + LPCWSTR pFirst = nullptr; + size_t i = 0; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + // Get property-to-trim name + hr = WcaGetProperty(TrimProp, (LPWSTR*)szPropName); + ExitOnFailure(hr, "Failed getting %ls", TrimProp); + if (szPropName.IsNullOrEmpty()) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No property name to trim..."); + ExitFunction(); + } + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Will trim property '%ls'", (LPCWSTR)szPropName); + + // Get string-to-trim + hr = WcaGetProperty((LPCWSTR)szPropName, (LPWSTR*)szFullString); + ExitOnFailure(hr, "Failed getting %ls", (LPCWSTR)szPropName); + if (szFullString.IsNullOrEmpty()) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No string to trim..."); + ExitFunction(); + } + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Will trim string '%ls'", (LPCWSTR)szFullString); + + // Trim right (i is unsigned, so after 0 it will be MAX_SIZE) + for (i = szFullString.StrLen() - 1; i < szFullString.StrLen(); --i) + { + switch (((LPCWSTR)szFullString)[i]) + { + case L' ': + case L'\r': + case L'\n': + case L'\t': + case L'\v': + ((LPWSTR)szFullString)[i] = NULL; + continue; + + default: + break; + } + break; + } + + // Trim left + for (i = 0; i < szFullString.StrLen(); ++i) + { + switch (((LPCWSTR)szFullString)[i]) + { + case L' ': + case L'\r': + case L'\n': + case L'\t': + case L'\v': + continue; + + default: + break; + } + break; + } + + if (i == szFullString.StrLen()) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "%ls is all white-spaces", szPropName); + + hr = WcaSetProperty(szPropName, L""); + ExitOnFailure(hr, "Failed setting %ls", (LPCWSTR)szPropName); + } + + pFirst = i + (LPCWSTR)szFullString; + hr = WcaSetProperty(szPropName, pFirst); + ExitOnFailure(hr, "Failed setting %ls", (LPCWSTR)szPropName); + +LExit: + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +extern "C" UINT __stdcall ToLowerCase(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + PMSIHANDLE hView; + PMSIHANDLE hRecord; + bool bIgnoreErrors = false; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + // Ensure table PSW_XmlSearch exists. + hr = WcaTableExists(L"PSW_ToLowerCase"); + ExitOnFailure(hr, "Failed to check if table exists 'PSW_ToLowerCase'"); + ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_ToLowerCase'. Have you authored 'PanelSw:ToLowerCase' entries in WiX code?"); + + // Execute view + hr = WcaOpenExecuteView(L"SELECT `Property_` FROM `PSW_ToLowerCase`", &hView); + ExitOnFailure(hr, "Failed to execute SQL query on 'PSW_ToLowerCase'."); + + // Iterate records + while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) + { + ExitOnFailure(hr, "Failed to fetch record."); + + // Get fields + CWixString szProperty, szValue; + + hr = WcaGetRecordString(hRecord, 1, (LPWSTR*)szProperty); + ExitOnFailure(hr, "Failed to get Property_."); + + hr = WcaGetProperty(szProperty, (LPWSTR*)szValue); + ExitOnFailure(hr, "Failed to get property '%ls' value.", (LPCWSTR)szProperty); + + StrStringToLower(szValue); + + hr = WcaSetProperty(szProperty, szValue); + ExitOnFailure(hr, "Failed setting property"); + } + hr = ERROR_SUCCESS; + +LExit: + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} diff --git a/PanelSwCustomActions/TaskScheduler.cpp b/src/PanelSwCustomActions/TaskScheduler.cpp similarity index 100% rename from PanelSwCustomActions/TaskScheduler.cpp rename to src/PanelSwCustomActions/TaskScheduler.cpp diff --git a/PanelSwCustomActions/TaskScheduler.h b/src/PanelSwCustomActions/TaskScheduler.h similarity index 100% rename from PanelSwCustomActions/TaskScheduler.h rename to src/PanelSwCustomActions/TaskScheduler.h diff --git a/PanelSwCustomActions/Telemetry.cpp b/src/PanelSwCustomActions/Telemetry.cpp similarity index 96% rename from PanelSwCustomActions/Telemetry.cpp rename to src/PanelSwCustomActions/Telemetry.cpp index 0407cd01..b4fa8bb2 100644 --- a/PanelSwCustomActions/Telemetry.cpp +++ b/src/PanelSwCustomActions/Telemetry.cpp @@ -1,286 +1,286 @@ -#include "pch.h" -#include "Telemetry.h" -#include "telemetryDetails.pb.h" -#include -#pragma comment (lib, "Winhttp.lib") -using namespace ::com::panelsw::ca; -using namespace google::protobuf; - -#define TELEMETRY_QUERY L"SELECT `Id`, `Url`, `Page`, `Method`, `Data`, `Flags`, `Condition` FROM `PSW_Telemetry`" -enum TelemetryQuery { Id=1, Url=2, Page = 3, Method=4, Data=5, Flags=6, Condition=7 }; - -enum TelemetryFlags -{ - None = 0, - OnExecute = 1, - OnCommit = 2, - OnRollback = 4, - - Secure = 8 -}; - -extern "C" UINT __stdcall Telemetry(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - PMSIHANDLE hView; - PMSIHANDLE hRecord; - CTelemetry oRollbackTelemetry; - CTelemetry oCommitTelemetry; - CTelemetry oDeferredTelemetry; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - // Ensure table PSW_Telemetry exists. - hr = WcaTableExists(L"PSW_Telemetry"); - ExitOnFailure(hr, "Failed to check if table exists 'PSW_Telemetry'"); - ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_Telemetry'. Have you authored 'PanelSw:Telemetry' entries in WiX code?"); - - // Execute view - hr = WcaOpenExecuteView(TELEMETRY_QUERY, &hView); - ExitOnFailure(hr, "Failed to execute SQL query '%ls'.", TELEMETRY_QUERY); - - // Iterate records - while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) - { - ExitOnFailure(hr, "Failed to fetch record."); - - // Get fields - CWixString szId, szUrl, szPage, szMethod, szData, szCondition; - int nFlags = 0; - BOOL bSecure = FALSE; - - hr = WcaGetRecordString(hRecord, TelemetryQuery::Id, (LPWSTR*)szId); - ExitOnFailure(hr, "Failed to get Id."); - hr = WcaGetRecordFormattedString(hRecord, TelemetryQuery::Url, (LPWSTR*)szUrl); - ExitOnFailure(hr, "Failed to get URL."); - hr = WcaGetRecordFormattedString(hRecord, TelemetryQuery::Page, (LPWSTR*)szPage); - ExitOnFailure(hr, "Failed to get Page."); - hr = WcaGetRecordFormattedString(hRecord, TelemetryQuery::Method, (LPWSTR*)szMethod); - ExitOnFailure(hr, "Failed to get Method."); - hr = WcaGetRecordFormattedString(hRecord, TelemetryQuery::Data, (LPWSTR*)szData); - ExitOnFailure(hr, "Failed to get Data."); - hr = WcaGetRecordInteger(hRecord, TelemetryQuery::Flags, &nFlags); - ExitOnFailure(hr, "Failed to get Flags."); - hr = WcaGetRecordString(hRecord, TelemetryQuery::Condition, (LPWSTR*)szCondition); - ExitOnFailure(hr, "Failed to get Condition."); - - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Will post telemetry: Id=%ls\nUrl=%ls\nPage=%ls\nData=%ls\nFlags=%i\nCondition=%ls", (LPCWSTR)szId, (LPCWSTR)szUrl, (LPCWSTR)szPage, (LPCWSTR)szData, nFlags, (LPCWSTR)szCondition); - - // Test condition - MSICONDITION condRes = ::MsiEvaluateConditionW(hInstall, szCondition); - switch (condRes) - { - case MSICONDITION::MSICONDITION_NONE: - case MSICONDITION::MSICONDITION_TRUE: - WcaLog(LOGMSG_STANDARD, "Condition evaluated to true / none."); - break; - - case MSICONDITION::MSICONDITION_FALSE: - WcaLog(LOGMSG_STANDARD, "Skipping. Condition evaluated to false"); - continue; - - case MSICONDITION::MSICONDITION_ERROR: - hr = E_FAIL; - ExitOnFailure(hr, "Bad Condition field"); - } - - if ((nFlags & TelemetryFlags::Secure) == TelemetryFlags::Secure) - { - bSecure = TRUE; - } - - if ((nFlags & TelemetryFlags::OnExecute) == TelemetryFlags::OnExecute) - { - hr = oDeferredTelemetry.AddPost(szUrl, szPage, szMethod, szData, bSecure); - ExitOnFailure(hr, "Failed creating custom action data for deferred action."); - } - if ((nFlags & TelemetryFlags::OnCommit) == TelemetryFlags::OnCommit) - { - hr = oCommitTelemetry.AddPost(szUrl, szPage, szMethod, szData, bSecure); - ExitOnFailure(hr, "Failed creating custom action data for commit action."); - } - if ((nFlags & TelemetryFlags::OnRollback) == TelemetryFlags::OnRollback) - { - hr = oRollbackTelemetry.AddPost(szUrl, szPage, szMethod, szData, bSecure); - ExitOnFailure(hr, "Failed creating custom action data for rollback action."); - } - } - - // Schedule actions. - hr = oRollbackTelemetry.DoDeferredAction(L"Telemetry_rollback"); - ExitOnFailure(hr, "Failed scheduling rollback action."); - - hr = oDeferredTelemetry.DoDeferredAction(L"Telemetry_deferred"); - ExitOnFailure(hr, "Failed scheduling deferred action."); - - hr = oCommitTelemetry.DoDeferredAction(L"Telemetry_commit"); - ExitOnFailure(hr, "Failed scheduling commit action."); - -LExit: - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - -HRESULT CTelemetry::AddPost(LPCWSTR szUrl, LPCWSTR szPage, LPCWSTR szMethod, LPCWSTR szData, BOOL bSecure) -{ - HRESULT hr = S_OK; - ::com::panelsw::ca::Command* pCmd = nullptr; - TelemetryDetails* pDetails = nullptr; - ::std::string* pAny = nullptr; - bool bRes = true; - - hr = AddCommand("CTelemetry", &pCmd); - ExitOnFailure(hr, "Failed to add command"); - - pDetails = new TelemetryDetails(); - ExitOnNull(pDetails, hr, E_FAIL, "Failed allocating details"); - - pDetails->set_url(szUrl, WSTR_BYTE_SIZE(szUrl)); - pDetails->set_page(szPage, WSTR_BYTE_SIZE(szPage)); - pDetails->set_method(szMethod, WSTR_BYTE_SIZE(szMethod)); - pDetails->set_data(szData, WSTR_BYTE_SIZE(szData)); - pDetails->set_secure(bSecure); - - pAny = pCmd->mutable_details(); - ExitOnNull(pAny, hr, E_FAIL, "Failed allocating any"); - - bRes = pDetails->SerializeToString(pAny); - ExitOnNull(bRes, hr, E_FAIL, "Failed serializing command details"); - -LExit: - return hr; -} - -HRESULT CTelemetry::DeferredExecute(const ::std::string& command) -{ - HRESULT hr = S_OK; - BOOL bRes = TRUE; - LPCWSTR szUrl = nullptr; - LPCWSTR szPage = nullptr; - LPCWSTR szData = nullptr; - LPCWSTR szMethod = nullptr; - TelemetryDetails details; - - bRes = details.ParseFromString(command); - ExitOnNull(bRes, hr, E_INVALIDARG, "Failed unpacking TelemetryDetails"); - - szUrl = (LPCWSTR)(LPVOID)details.url().data(); - szPage = (LPCWSTR)(LPVOID)details.page().data(); - szData = (LPCWSTR)(LPVOID)details.data().data(); - szMethod = (LPCWSTR)(LPVOID)details.method().data(); - - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Posting telemetry: Url=%ls Page=%ls Method=%ls Data=%ls Secure=%i", szUrl, szPage, szMethod, szData, details.secure()); - - hr = Post(szUrl, szPage, szMethod, szData, details.secure()); - ExitOnFailure(hr, "Failed to post Data '%ls' to URL '%ls%ls'", szData, szUrl, szPage); - -LExit: - return hr; -} - -HRESULT CTelemetry::Post(LPCWSTR szUrl, LPCWSTR szPage, LPCWSTR szMethod, LPCWSTR szData, BOOL bSecure) -{ - HRESULT hr = S_OK; - DWORD dwSize = 0; - DWORD dwPrevSize = 0; - DWORD dwDownloaded = 0; - LPSTR pszOutBuffer = nullptr; - BOOL bResults = FALSE; - HINTERNET hSession = NULL; - HINTERNET hConnect = NULL; - HINTERNET hRequest = NULL; - - // Use WinHttpOpen to obtain a session handle. - hSession = ::WinHttpOpen(L"PanelSwCustomActions/1.0", - WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, - WINHTTP_NO_PROXY_NAME, - WINHTTP_NO_PROXY_BYPASS, 0); - ExitOnNullWithLastError(hSession, hr, "Failed opening HTTP session"); - - // Specify an HTTP server. - hConnect = ::WinHttpConnect(hSession, szUrl, - bSecure ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT, 0); - ExitOnNullWithLastError(hConnect, hr, "Failed connecting to URL"); - - // Create an HTTP request handle. - hRequest = ::WinHttpOpenRequest(hConnect, szMethod, szPage, nullptr, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, - bSecure ? WINHTTP_FLAG_SECURE : 0); - ExitOnNullWithLastError(hRequest, hr, "Failed opening request"); - - // Get data size - if (szData && *szData) - { - dwSize = ::wcslen(szData); - } - - // Send a request. - bResults = ::WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, (LPVOID)szData, dwSize, dwSize, 0); - ExitOnNull(bResults, hr, E_FAIL, "Failed sending HTTP request"); - - // End the request. - bResults = ::WinHttpReceiveResponse(hRequest, nullptr); - ExitOnNull(bResults, hr, E_FAIL, "Failed receiving HTTP response"); - - // Keep checking for data until there is nothing left. - do - { - // Check for available data. - dwSize = 0; - bResults = ::WinHttpQueryDataAvailable(hRequest, &dwSize); - ExitOnNullWithLastError(bResults, hr, "Failed querying available data."); - - // No more data. - if (dwSize == 0) - { - break; - } - - // Allocate space for the buffer. - if (dwSize > dwPrevSize) - { - // Release previous buffer. - if (pszOutBuffer) - { - delete[] pszOutBuffer; - pszOutBuffer = nullptr; - } - - pszOutBuffer = new char[dwSize + 1]; - ExitOnNull(pszOutBuffer, hr, E_FAIL, "Failed allocating memory"); - dwPrevSize = dwSize; - } - - // Read the Data. - ::ZeroMemory(pszOutBuffer, dwSize + 1); - - bResults = ::WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded); - ExitOnNullWithLastError(bResults, hr, "Failed reading data"); - ExitOnNull(dwDownloaded, hr, E_FAIL, "Failed reading data (dwDownloaded=0)"); - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "%hs", pszOutBuffer); - - } while (dwSize > 0); - -LExit: - // Close any open handles. - if (hRequest) - { - ::WinHttpCloseHandle(hRequest); - } - if (hConnect) - { - ::WinHttpCloseHandle(hConnect); - } - if (hSession) - { - ::WinHttpCloseHandle(hSession); - } - if (pszOutBuffer) - { - delete[] pszOutBuffer; - } - - return hr; -} +#include "pch.h" +#include "Telemetry.h" +#include "telemetryDetails.pb.h" +#include +#pragma comment (lib, "Winhttp.lib") +using namespace ::com::panelsw::ca; +using namespace google::protobuf; + +#define TELEMETRY_QUERY L"SELECT `Id`, `Url`, `Page`, `Method`, `Data`, `Flags`, `Condition` FROM `PSW_Telemetry`" +enum TelemetryQuery { Id=1, Url=2, Page = 3, Method=4, Data=5, Flags=6, Condition=7 }; + +enum TelemetryFlags +{ + None = 0, + OnExecute = 1, + OnCommit = 2, + OnRollback = 4, + + Secure = 8 +}; + +extern "C" UINT __stdcall Telemetry(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + PMSIHANDLE hView; + PMSIHANDLE hRecord; + CTelemetry oRollbackTelemetry; + CTelemetry oCommitTelemetry; + CTelemetry oDeferredTelemetry; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + // Ensure table PSW_Telemetry exists. + hr = WcaTableExists(L"PSW_Telemetry"); + ExitOnFailure(hr, "Failed to check if table exists 'PSW_Telemetry'"); + ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_Telemetry'. Have you authored 'PanelSw:Telemetry' entries in WiX code?"); + + // Execute view + hr = WcaOpenExecuteView(TELEMETRY_QUERY, &hView); + ExitOnFailure(hr, "Failed to execute SQL query '%ls'.", TELEMETRY_QUERY); + + // Iterate records + while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) + { + ExitOnFailure(hr, "Failed to fetch record."); + + // Get fields + CWixString szId, szUrl, szPage, szMethod, szData, szCondition; + int nFlags = 0; + BOOL bSecure = FALSE; + + hr = WcaGetRecordString(hRecord, TelemetryQuery::Id, (LPWSTR*)szId); + ExitOnFailure(hr, "Failed to get Id."); + hr = WcaGetRecordFormattedString(hRecord, TelemetryQuery::Url, (LPWSTR*)szUrl); + ExitOnFailure(hr, "Failed to get URL."); + hr = WcaGetRecordFormattedString(hRecord, TelemetryQuery::Page, (LPWSTR*)szPage); + ExitOnFailure(hr, "Failed to get Page."); + hr = WcaGetRecordFormattedString(hRecord, TelemetryQuery::Method, (LPWSTR*)szMethod); + ExitOnFailure(hr, "Failed to get Method."); + hr = WcaGetRecordFormattedString(hRecord, TelemetryQuery::Data, (LPWSTR*)szData); + ExitOnFailure(hr, "Failed to get Data."); + hr = WcaGetRecordInteger(hRecord, TelemetryQuery::Flags, &nFlags); + ExitOnFailure(hr, "Failed to get Flags."); + hr = WcaGetRecordString(hRecord, TelemetryQuery::Condition, (LPWSTR*)szCondition); + ExitOnFailure(hr, "Failed to get Condition."); + + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Will post telemetry: Id=%ls\nUrl=%ls\nPage=%ls\nData=%ls\nFlags=%i\nCondition=%ls", (LPCWSTR)szId, (LPCWSTR)szUrl, (LPCWSTR)szPage, (LPCWSTR)szData, nFlags, (LPCWSTR)szCondition); + + // Test condition + MSICONDITION condRes = ::MsiEvaluateConditionW(hInstall, szCondition); + switch (condRes) + { + case MSICONDITION::MSICONDITION_NONE: + case MSICONDITION::MSICONDITION_TRUE: + WcaLog(LOGMSG_STANDARD, "Condition evaluated to true / none."); + break; + + case MSICONDITION::MSICONDITION_FALSE: + WcaLog(LOGMSG_STANDARD, "Skipping. Condition evaluated to false"); + continue; + + case MSICONDITION::MSICONDITION_ERROR: + hr = E_FAIL; + ExitOnFailure(hr, "Bad Condition field"); + } + + if ((nFlags & TelemetryFlags::Secure) == TelemetryFlags::Secure) + { + bSecure = TRUE; + } + + if ((nFlags & TelemetryFlags::OnExecute) == TelemetryFlags::OnExecute) + { + hr = oDeferredTelemetry.AddPost(szUrl, szPage, szMethod, szData, bSecure); + ExitOnFailure(hr, "Failed creating custom action data for deferred action."); + } + if ((nFlags & TelemetryFlags::OnCommit) == TelemetryFlags::OnCommit) + { + hr = oCommitTelemetry.AddPost(szUrl, szPage, szMethod, szData, bSecure); + ExitOnFailure(hr, "Failed creating custom action data for commit action."); + } + if ((nFlags & TelemetryFlags::OnRollback) == TelemetryFlags::OnRollback) + { + hr = oRollbackTelemetry.AddPost(szUrl, szPage, szMethod, szData, bSecure); + ExitOnFailure(hr, "Failed creating custom action data for rollback action."); + } + } + + // Schedule actions. + hr = oRollbackTelemetry.DoDeferredAction(L"Telemetry_rollback"); + ExitOnFailure(hr, "Failed scheduling rollback action."); + + hr = oDeferredTelemetry.DoDeferredAction(L"Telemetry_deferred"); + ExitOnFailure(hr, "Failed scheduling deferred action."); + + hr = oCommitTelemetry.DoDeferredAction(L"Telemetry_commit"); + ExitOnFailure(hr, "Failed scheduling commit action."); + +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +HRESULT CTelemetry::AddPost(LPCWSTR szUrl, LPCWSTR szPage, LPCWSTR szMethod, LPCWSTR szData, BOOL bSecure) +{ + HRESULT hr = S_OK; + ::com::panelsw::ca::Command* pCmd = nullptr; + TelemetryDetails* pDetails = nullptr; + ::std::string* pAny = nullptr; + bool bRes = true; + + hr = AddCommand("CTelemetry", &pCmd); + ExitOnFailure(hr, "Failed to add command"); + + pDetails = new TelemetryDetails(); + ExitOnNull(pDetails, hr, E_FAIL, "Failed allocating details"); + + pDetails->set_url(szUrl, WSTR_BYTE_SIZE(szUrl)); + pDetails->set_page(szPage, WSTR_BYTE_SIZE(szPage)); + pDetails->set_method(szMethod, WSTR_BYTE_SIZE(szMethod)); + pDetails->set_data(szData, WSTR_BYTE_SIZE(szData)); + pDetails->set_secure(bSecure); + + pAny = pCmd->mutable_details(); + ExitOnNull(pAny, hr, E_FAIL, "Failed allocating any"); + + bRes = pDetails->SerializeToString(pAny); + ExitOnNull(bRes, hr, E_FAIL, "Failed serializing command details"); + +LExit: + return hr; +} + +HRESULT CTelemetry::DeferredExecute(const ::std::string& command) +{ + HRESULT hr = S_OK; + BOOL bRes = TRUE; + LPCWSTR szUrl = nullptr; + LPCWSTR szPage = nullptr; + LPCWSTR szData = nullptr; + LPCWSTR szMethod = nullptr; + TelemetryDetails details; + + bRes = details.ParseFromString(command); + ExitOnNull(bRes, hr, E_INVALIDARG, "Failed unpacking TelemetryDetails"); + + szUrl = (LPCWSTR)(LPVOID)details.url().data(); + szPage = (LPCWSTR)(LPVOID)details.page().data(); + szData = (LPCWSTR)(LPVOID)details.data().data(); + szMethod = (LPCWSTR)(LPVOID)details.method().data(); + + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "Posting telemetry: Url=%ls Page=%ls Method=%ls Data=%ls Secure=%i", szUrl, szPage, szMethod, szData, details.secure()); + + hr = Post(szUrl, szPage, szMethod, szData, details.secure()); + ExitOnFailure(hr, "Failed to post Data '%ls' to URL '%ls%ls'", szData, szUrl, szPage); + +LExit: + return hr; +} + +HRESULT CTelemetry::Post(LPCWSTR szUrl, LPCWSTR szPage, LPCWSTR szMethod, LPCWSTR szData, BOOL bSecure) +{ + HRESULT hr = S_OK; + DWORD dwSize = 0; + DWORD dwPrevSize = 0; + DWORD dwDownloaded = 0; + LPSTR pszOutBuffer = nullptr; + BOOL bResults = FALSE; + HINTERNET hSession = NULL; + HINTERNET hConnect = NULL; + HINTERNET hRequest = NULL; + + // Use WinHttpOpen to obtain a session handle. + hSession = ::WinHttpOpen(L"PanelSwCustomActions/1.0", + WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, + WINHTTP_NO_PROXY_NAME, + WINHTTP_NO_PROXY_BYPASS, 0); + ExitOnNullWithLastError(hSession, hr, "Failed opening HTTP session"); + + // Specify an HTTP server. + hConnect = ::WinHttpConnect(hSession, szUrl, + bSecure ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT, 0); + ExitOnNullWithLastError(hConnect, hr, "Failed connecting to URL"); + + // Create an HTTP request handle. + hRequest = ::WinHttpOpenRequest(hConnect, szMethod, szPage, nullptr, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, + bSecure ? WINHTTP_FLAG_SECURE : 0); + ExitOnNullWithLastError(hRequest, hr, "Failed opening request"); + + // Get data size + if (szData && *szData) + { + dwSize = ::wcslen(szData); + } + + // Send a request. + bResults = ::WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, (LPVOID)szData, dwSize, dwSize, 0); + ExitOnNull(bResults, hr, E_FAIL, "Failed sending HTTP request"); + + // End the request. + bResults = ::WinHttpReceiveResponse(hRequest, nullptr); + ExitOnNull(bResults, hr, E_FAIL, "Failed receiving HTTP response"); + + // Keep checking for data until there is nothing left. + do + { + // Check for available data. + dwSize = 0; + bResults = ::WinHttpQueryDataAvailable(hRequest, &dwSize); + ExitOnNullWithLastError(bResults, hr, "Failed querying available data."); + + // No more data. + if (dwSize == 0) + { + break; + } + + // Allocate space for the buffer. + if (dwSize > dwPrevSize) + { + // Release previous buffer. + if (pszOutBuffer) + { + delete[] pszOutBuffer; + pszOutBuffer = nullptr; + } + + pszOutBuffer = new char[dwSize + 1]; + ExitOnNull(pszOutBuffer, hr, E_FAIL, "Failed allocating memory"); + dwPrevSize = dwSize; + } + + // Read the Data. + ::ZeroMemory(pszOutBuffer, dwSize + 1); + + bResults = ::WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded); + ExitOnNullWithLastError(bResults, hr, "Failed reading data"); + ExitOnNull(dwDownloaded, hr, E_FAIL, "Failed reading data (dwDownloaded=0)"); + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "%hs", pszOutBuffer); + + } while (dwSize > 0); + +LExit: + // Close any open handles. + if (hRequest) + { + ::WinHttpCloseHandle(hRequest); + } + if (hConnect) + { + ::WinHttpCloseHandle(hConnect); + } + if (hSession) + { + ::WinHttpCloseHandle(hSession); + } + if (pszOutBuffer) + { + delete[] pszOutBuffer; + } + + return hr; +} diff --git a/PanelSwCustomActions/Telemetry.h b/src/PanelSwCustomActions/Telemetry.h similarity index 95% rename from PanelSwCustomActions/Telemetry.h rename to src/PanelSwCustomActions/Telemetry.h index cf9637aa..1d9f265d 100644 --- a/PanelSwCustomActions/Telemetry.h +++ b/src/PanelSwCustomActions/Telemetry.h @@ -1,20 +1,20 @@ -#pragma once -#include "../CaCommon/DeferredActionBase.h" - -class CTelemetry : - public CDeferredActionBase -{ -public: - - CTelemetry() : CDeferredActionBase("Telemetry") { } - - - HRESULT AddPost(LPCWSTR szUrl, LPCWSTR szPage, LPCWSTR szMethod, LPCWSTR szData, BOOL bSecure); - -protected: - - HRESULT DeferredExecute(const ::std::string& command) override; - -private: - HRESULT Post(LPCWSTR szUrl, LPCWSTR szPage, LPCWSTR szMethod, LPCWSTR szData, BOOL bSecure); +#pragma once +#include "../CaCommon/DeferredActionBase.h" + +class CTelemetry : + public CDeferredActionBase +{ +public: + + CTelemetry() : CDeferredActionBase("Telemetry") { } + + + HRESULT AddPost(LPCWSTR szUrl, LPCWSTR szPage, LPCWSTR szMethod, LPCWSTR szData, BOOL bSecure); + +protected: + + HRESULT DeferredExecute(const ::std::string& command) override; + +private: + HRESULT Post(LPCWSTR szUrl, LPCWSTR szPage, LPCWSTR szMethod, LPCWSTR szData, BOOL bSecure); }; \ No newline at end of file diff --git a/PanelSwCustomActions/TerminateSuccessfully.cpp b/src/PanelSwCustomActions/TerminateSuccessfully.cpp old mode 100755 new mode 100644 similarity index 96% rename from PanelSwCustomActions/TerminateSuccessfully.cpp rename to src/PanelSwCustomActions/TerminateSuccessfully.cpp index 6cffc901..cecf15b8 --- a/PanelSwCustomActions/TerminateSuccessfully.cpp +++ b/src/PanelSwCustomActions/TerminateSuccessfully.cpp @@ -1,8 +1,8 @@ -#include "pch.h" - -extern "C" UINT __stdcall TerminateSuccessfully(MSIHANDLE hInstall) -{ - WcaInitialize(hInstall, __FUNCTION__); - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Terminating Successfully"); - return WcaFinalize(ERROR_NO_MORE_ITEMS); -} +#include "pch.h" + +extern "C" UINT __stdcall TerminateSuccessfully(MSIHANDLE hInstall) +{ + WcaInitialize(hInstall, __FUNCTION__); + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "Terminating Successfully"); + return WcaFinalize(ERROR_NO_MORE_ITEMS); +} diff --git a/PanelSwCustomActions/TopShelfService.cpp b/src/PanelSwCustomActions/TopShelfService.cpp similarity index 100% rename from PanelSwCustomActions/TopShelfService.cpp rename to src/PanelSwCustomActions/TopShelfService.cpp diff --git a/PanelSwCustomActions/TopShelfService.h b/src/PanelSwCustomActions/TopShelfService.h similarity index 100% rename from PanelSwCustomActions/TopShelfService.h rename to src/PanelSwCustomActions/TopShelfService.h diff --git a/PanelSwCustomActions/Unzip.cpp b/src/PanelSwCustomActions/Unzip.cpp similarity index 100% rename from PanelSwCustomActions/Unzip.cpp rename to src/PanelSwCustomActions/Unzip.cpp diff --git a/PanelSwCustomActions/Unzip.h b/src/PanelSwCustomActions/Unzip.h similarity index 100% rename from PanelSwCustomActions/Unzip.h rename to src/PanelSwCustomActions/Unzip.h diff --git a/PanelSwCustomActions/VersionCompare.cpp b/src/PanelSwCustomActions/VersionCompare.cpp similarity index 100% rename from PanelSwCustomActions/VersionCompare.cpp rename to src/PanelSwCustomActions/VersionCompare.cpp diff --git a/PanelSwCustomActions/WmiSearch.cpp b/src/PanelSwCustomActions/WmiSearch.cpp similarity index 100% rename from PanelSwCustomActions/WmiSearch.cpp rename to src/PanelSwCustomActions/WmiSearch.cpp diff --git a/PanelSwCustomActions/XmlSearch.cpp b/src/PanelSwCustomActions/XmlSearch.cpp similarity index 96% rename from PanelSwCustomActions/XmlSearch.cpp rename to src/PanelSwCustomActions/XmlSearch.cpp index 0c735957..06721fff 100644 --- a/PanelSwCustomActions/XmlSearch.cpp +++ b/src/PanelSwCustomActions/XmlSearch.cpp @@ -1,262 +1,262 @@ -#include "pch.h" -#include "..\CaCommon\DeferredActionBase.h" -#include -#include -#include -#include -#pragma comment( lib, "msxml6.lib") - -#define XmlSearchQuery L"SELECT `Id`, `Property_`, `FilePath`, `Expression`, `Language`, `Namespaces`, `Match`, `Condition` FROM `PSW_XmlSearch`" -enum eXmlSearchQueryQuery { Id = 1, Property_, FilePath, Expression, Language, Namespaces, Match, Condition }; - -enum eXmlMatch -{ - first, - all, - enforceSingle -}; - -static HRESULT QueryXml(LPCWSTR pFile, LPCWSTR pExpression, LPCWSTR Language, LPCWSTR Namespaces, eXmlMatch eMatch, LPCWSTR pProperty); - -extern "C" UINT __stdcall XmlSearch(MSIHANDLE hInstall) -{ - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - PMSIHANDLE hView; - PMSIHANDLE hRecord; - - hr = WcaInitialize(hInstall, __FUNCTION__); - ExitOnFailure(hr, "Failed to initialize"); - WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); - - hr = ::CoInitialize(nullptr); - ExitOnFailure(hr, "Failed to CoInitialize"); - - // Ensure table PSW_XmlSearch exists. - hr = WcaTableExists(L"PSW_XmlSearch"); - ExitOnFailure(hr, "Failed to check if table exists 'PSW_XmlSearch'"); - ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_XmlSearch'. Have you authored 'PanelSw:XmlSearch' entries in WiX code?"); - - // Execute view - hr = WcaOpenExecuteView(XmlSearchQuery, &hView); - ExitOnFailure(hr, "Failed to execute SQL query on 'PSW_XmlSearch'."); - - // Iterate records - while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) - { - ExitOnFailure(hr, "Failed to fetch record."); - - // Get fields - CWixString szId; - CWixString szProperty; - CWixString szFilePath; - CWixString szExpression, szUnformattedExpression; - CWixString szLanguage; - CWixString szNamespaces; - CWixString szCondition; - eXmlMatch eMatch = eXmlMatch::first; - - hr = WcaGetRecordString(hRecord, eXmlSearchQueryQuery::Id, (LPWSTR*)szId); - ExitOnFailure(hr, "Failed to get Id."); - hr = WcaGetRecordString(hRecord, eXmlSearchQueryQuery::Property_, (LPWSTR*)szProperty); - ExitOnFailure(hr, "Failed to get Property_."); - hr = WcaGetRecordFormattedString(hRecord, eXmlSearchQueryQuery::FilePath, (LPWSTR*)szFilePath); - ExitOnFailure(hr, "Failed to get FilePath."); - hr = WcaGetRecordString(hRecord, eXmlSearchQueryQuery::Expression, (LPWSTR*)szUnformattedExpression); - ExitOnFailure(hr, "Failed to get Expression."); - hr = WcaGetRecordString(hRecord, eXmlSearchQueryQuery::Language, (LPWSTR*)szLanguage); - ExitOnFailure(hr, "Failed to get Language."); - hr = WcaGetRecordString(hRecord, eXmlSearchQueryQuery::Namespaces, (LPWSTR*)szNamespaces); - ExitOnFailure(hr, "Failed to get Namespaces."); - hr = WcaGetRecordInteger(hRecord, eXmlSearchQueryQuery::Match, (int*)&eMatch); - ExitOnFailure(hr, "Failed to get Match."); - hr = WcaGetRecordString(hRecord, eXmlSearchQueryQuery::Condition, (LPWSTR*)szCondition); - ExitOnFailure(hr, "Failed to get Condition."); - - // Test condition - if (!szCondition.IsNullOrEmpty()) - { - const MSICONDITION condRes = ::MsiEvaluateConditionW(hInstall, szCondition); - switch (condRes) - { - case MSICONDITION::MSICONDITION_NONE: - case MSICONDITION::MSICONDITION_TRUE: - WcaLog(LOGMSG_STANDARD, "Condition evaluated to true / none."); - break; - - case MSICONDITION::MSICONDITION_FALSE: - WcaLog(LOGMSG_STANDARD, "Skipping. Condition evaluated to false"); - continue; - - case MSICONDITION::MSICONDITION_ERROR: - hr = E_FAIL; - ExitOnFailure(hr, "Bad Condition field"); - } - } - - hr = szExpression.MsiFormat(szUnformattedExpression); - ExitOnFailure(hr, "Failed formatting query."); - - CDeferredActionBase::LogUnformatted(LOGLEVEL::LOGMSG_STANDARD, false, L"Running Expression '%ls' on '%ls'", szExpression.Obfuscated(), (LPCWSTR)szFilePath); - hr = QueryXml(szFilePath, szExpression, szLanguage, szNamespaces, eMatch, szProperty); - ExitOnFailure(hr, "Failed to query XML."); - } - - hr = ERROR_SUCCESS; - -LExit: - ::CoUninitialize(); - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - -static HRESULT QueryXml(LPCWSTR pFile, LPCWSTR pExpression, LPCWSTR szLanguage, LPCWSTR szNamespaces, eXmlMatch eMatch, LPCWSTR pProperty) -{ - HRESULT hr = S_OK; - - ExitOnNull(pFile, hr, E_INVALIDARG, "pFile is null"); - ExitOnNull(pExpression, hr, E_INVALIDARG, "pExpression is null"); - ExitOnNull(pProperty, hr, E_INVALIDARG, "pProperty is null"); - - if (!FileExistsEx(pFile, nullptr)) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "File doesn't exist: '%ls'", pFile); - ExitFunction(); - } - - try - { - CComPtr pXmlDoc; - CComPtr pNodeList; - CComVariant filePath; - VARIANT_BOOL isXmlSuccess; - LONG nodeCount = 0; - LONG maxMatches = 0; - CComBSTR result(L""); - CComBSTR delimiter(L"[~]"); - - // Create XML doc. - hr = ::CoCreateInstance(CLSID_DOMDocument, nullptr, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pXmlDoc); - ExitOnFailure(hr, "Failed to CoCreateInstance CLSID_DOMDocument"); - - // Load XML document - filePath = pFile; - hr = pXmlDoc->load(filePath, &isXmlSuccess); - ExitOnFailure(hr, "Failed to load XML"); - if (!isXmlSuccess) - { - hr = E_FAIL; - ExitOnFailure(hr, "Failed to load XML"); - } - - // Set language. - if (szLanguage && *szLanguage) - { - static const CComBSTR SelectionLanguage(L"SelectionLanguage"); - hr = pXmlDoc->setProperty(SelectionLanguage, CComVariant(szLanguage)); - ExitOnFailure(hr, "Failed setting SelectionLanguage"); - - CComVariant varTmp; - hr = pXmlDoc->getProperty(SelectionLanguage, &varTmp); - ExitOnFailure(hr, "Failed getting namespaces"); - - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "SelectionLanguage is %ls", varTmp.bstrVal); - } - - // Set namespaces. - if (szNamespaces && *szNamespaces) - { - static const CComBSTR SelectionNamespaces(L"SelectionNamespaces"); - hr = pXmlDoc->setProperty(SelectionNamespaces, CComVariant(szNamespaces)); - ExitOnFailure(hr, "Failed setting namespaces"); - - CComVariant varTmp; - hr = pXmlDoc->getProperty(SelectionNamespaces, &varTmp); - ExitOnFailure(hr, "Failed getting namespaces"); - - WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "SelectionNamespaces is %ls", varTmp.bstrVal); - } - - // Execute Expression - hr = pXmlDoc->selectNodes(CComBSTR(pExpression), &pNodeList); - ExitOnFailure(hr, "Failed to select XML nodes"); - ExitOnNull(pNodeList, hr, E_FAIL, "selectNodes returned NULL"); - - // Get match-count - hr = pNodeList->get_length(&nodeCount); - ExitOnFailure(hr, "Failed to get node count"); - - // Validate with request match parameter - switch (eMatch) - { - case first: - maxMatches = min(1, nodeCount); - break; - case all: - maxMatches = nodeCount; - break; - case enforceSingle: - if (nodeCount != 1) - { - hr = E_INVALIDARG; - ExitOnFailure(hr, "XmlSreach %i matches. Expected exactly one match", nodeCount); - } - maxMatches = 1; - break; - default: - hr = E_INVALIDARG; - ExitOnFailure(hr, "Wrong match parameter for XmlSreach."); - break; - } - - if (maxMatches == 0) - { - WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No matches found"); - ExitFunction(); - } - - for (LONG i = 0; i < maxMatches; ++i) - { - CComPtr pNode; - CComVariant nodeValue; - - hr = pNodeList->get_item(i, &pNode); - ExitOnFailure(hr, "Failed to get node."); - ExitOnNull(pNode.p, hr, E_FAIL, "Failed to get node."); - - hr = pNode->get_nodeValue(&nodeValue); - ExitOnFailure(hr, "Failed to get node's value."); - - hr = nodeValue.ChangeType(VT_BSTR); - ExitOnFailure(hr, "Failed to get node's value as string."); - - // Add result - hr = result.AppendBSTR(nodeValue.bstrVal); - ExitOnFailure(hr, "Failed to append result."); - - // Add delimiter (unless this is the last) - if (i < maxMatches - 1) - { - hr = result.AppendBSTR(delimiter); - ExitOnFailure(hr, "Failed to append delimiter."); - } - } - - // Put in property - hr = WcaSetProperty(pProperty, (LPWSTR)result); - } - catch (CAtlException ex) - { - hr = (HRESULT)ex; - ExitOnFailure(hr, "Failed querying XML"); - } - catch (...) - { - hr = E_FAIL; - ExitOnFailure(hr, "Failed querying XML"); - } - -LExit: - return hr; -} +#include "pch.h" +#include "..\CaCommon\DeferredActionBase.h" +#include +#include +#include +#include +#pragma comment( lib, "msxml6.lib") + +#define XmlSearchQuery L"SELECT `Id`, `Property_`, `FilePath`, `Expression`, `Language`, `Namespaces`, `Match`, `Condition` FROM `PSW_XmlSearch`" +enum eXmlSearchQueryQuery { Id = 1, Property_, FilePath, Expression, Language, Namespaces, Match, Condition }; + +enum eXmlMatch +{ + first, + all, + enforceSingle +}; + +static HRESULT QueryXml(LPCWSTR pFile, LPCWSTR pExpression, LPCWSTR Language, LPCWSTR Namespaces, eXmlMatch eMatch, LPCWSTR pProperty); + +extern "C" UINT __stdcall XmlSearch(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + PMSIHANDLE hView; + PMSIHANDLE hRecord; + + hr = WcaInitialize(hInstall, __FUNCTION__); + ExitOnFailure(hr, "Failed to initialize"); + WcaLog(LOGMSG_STANDARD, "Initialized from PanelSwCustomActions " FullVersion); + + hr = ::CoInitialize(nullptr); + ExitOnFailure(hr, "Failed to CoInitialize"); + + // Ensure table PSW_XmlSearch exists. + hr = WcaTableExists(L"PSW_XmlSearch"); + ExitOnFailure(hr, "Failed to check if table exists 'PSW_XmlSearch'"); + ExitOnNull((hr == S_OK), hr, E_FAIL, "Table does not exist 'PSW_XmlSearch'. Have you authored 'PanelSw:XmlSearch' entries in WiX code?"); + + // Execute view + hr = WcaOpenExecuteView(XmlSearchQuery, &hView); + ExitOnFailure(hr, "Failed to execute SQL query on 'PSW_XmlSearch'."); + + // Iterate records + while ((hr = WcaFetchRecord(hView, &hRecord)) != E_NOMOREITEMS) + { + ExitOnFailure(hr, "Failed to fetch record."); + + // Get fields + CWixString szId; + CWixString szProperty; + CWixString szFilePath; + CWixString szExpression, szUnformattedExpression; + CWixString szLanguage; + CWixString szNamespaces; + CWixString szCondition; + eXmlMatch eMatch = eXmlMatch::first; + + hr = WcaGetRecordString(hRecord, eXmlSearchQueryQuery::Id, (LPWSTR*)szId); + ExitOnFailure(hr, "Failed to get Id."); + hr = WcaGetRecordString(hRecord, eXmlSearchQueryQuery::Property_, (LPWSTR*)szProperty); + ExitOnFailure(hr, "Failed to get Property_."); + hr = WcaGetRecordFormattedString(hRecord, eXmlSearchQueryQuery::FilePath, (LPWSTR*)szFilePath); + ExitOnFailure(hr, "Failed to get FilePath."); + hr = WcaGetRecordString(hRecord, eXmlSearchQueryQuery::Expression, (LPWSTR*)szUnformattedExpression); + ExitOnFailure(hr, "Failed to get Expression."); + hr = WcaGetRecordString(hRecord, eXmlSearchQueryQuery::Language, (LPWSTR*)szLanguage); + ExitOnFailure(hr, "Failed to get Language."); + hr = WcaGetRecordString(hRecord, eXmlSearchQueryQuery::Namespaces, (LPWSTR*)szNamespaces); + ExitOnFailure(hr, "Failed to get Namespaces."); + hr = WcaGetRecordInteger(hRecord, eXmlSearchQueryQuery::Match, (int*)&eMatch); + ExitOnFailure(hr, "Failed to get Match."); + hr = WcaGetRecordString(hRecord, eXmlSearchQueryQuery::Condition, (LPWSTR*)szCondition); + ExitOnFailure(hr, "Failed to get Condition."); + + // Test condition + if (!szCondition.IsNullOrEmpty()) + { + const MSICONDITION condRes = ::MsiEvaluateConditionW(hInstall, szCondition); + switch (condRes) + { + case MSICONDITION::MSICONDITION_NONE: + case MSICONDITION::MSICONDITION_TRUE: + WcaLog(LOGMSG_STANDARD, "Condition evaluated to true / none."); + break; + + case MSICONDITION::MSICONDITION_FALSE: + WcaLog(LOGMSG_STANDARD, "Skipping. Condition evaluated to false"); + continue; + + case MSICONDITION::MSICONDITION_ERROR: + hr = E_FAIL; + ExitOnFailure(hr, "Bad Condition field"); + } + } + + hr = szExpression.MsiFormat(szUnformattedExpression); + ExitOnFailure(hr, "Failed formatting query."); + + CDeferredActionBase::LogUnformatted(LOGLEVEL::LOGMSG_STANDARD, false, L"Running Expression '%ls' on '%ls'", szExpression.Obfuscated(), (LPCWSTR)szFilePath); + hr = QueryXml(szFilePath, szExpression, szLanguage, szNamespaces, eMatch, szProperty); + ExitOnFailure(hr, "Failed to query XML."); + } + + hr = ERROR_SUCCESS; + +LExit: + ::CoUninitialize(); + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +static HRESULT QueryXml(LPCWSTR pFile, LPCWSTR pExpression, LPCWSTR szLanguage, LPCWSTR szNamespaces, eXmlMatch eMatch, LPCWSTR pProperty) +{ + HRESULT hr = S_OK; + + ExitOnNull(pFile, hr, E_INVALIDARG, "pFile is null"); + ExitOnNull(pExpression, hr, E_INVALIDARG, "pExpression is null"); + ExitOnNull(pProperty, hr, E_INVALIDARG, "pProperty is null"); + + if (!FileExistsEx(pFile, nullptr)) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "File doesn't exist: '%ls'", pFile); + ExitFunction(); + } + + try + { + CComPtr pXmlDoc; + CComPtr pNodeList; + CComVariant filePath; + VARIANT_BOOL isXmlSuccess; + LONG nodeCount = 0; + LONG maxMatches = 0; + CComBSTR result(L""); + CComBSTR delimiter(L"[~]"); + + // Create XML doc. + hr = ::CoCreateInstance(CLSID_DOMDocument, nullptr, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pXmlDoc); + ExitOnFailure(hr, "Failed to CoCreateInstance CLSID_DOMDocument"); + + // Load XML document + filePath = pFile; + hr = pXmlDoc->load(filePath, &isXmlSuccess); + ExitOnFailure(hr, "Failed to load XML"); + if (!isXmlSuccess) + { + hr = E_FAIL; + ExitOnFailure(hr, "Failed to load XML"); + } + + // Set language. + if (szLanguage && *szLanguage) + { + static const CComBSTR SelectionLanguage(L"SelectionLanguage"); + hr = pXmlDoc->setProperty(SelectionLanguage, CComVariant(szLanguage)); + ExitOnFailure(hr, "Failed setting SelectionLanguage"); + + CComVariant varTmp; + hr = pXmlDoc->getProperty(SelectionLanguage, &varTmp); + ExitOnFailure(hr, "Failed getting namespaces"); + + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "SelectionLanguage is %ls", varTmp.bstrVal); + } + + // Set namespaces. + if (szNamespaces && *szNamespaces) + { + static const CComBSTR SelectionNamespaces(L"SelectionNamespaces"); + hr = pXmlDoc->setProperty(SelectionNamespaces, CComVariant(szNamespaces)); + ExitOnFailure(hr, "Failed setting namespaces"); + + CComVariant varTmp; + hr = pXmlDoc->getProperty(SelectionNamespaces, &varTmp); + ExitOnFailure(hr, "Failed getting namespaces"); + + WcaLog(LOGLEVEL::LOGMSG_VERBOSE, "SelectionNamespaces is %ls", varTmp.bstrVal); + } + + // Execute Expression + hr = pXmlDoc->selectNodes(CComBSTR(pExpression), &pNodeList); + ExitOnFailure(hr, "Failed to select XML nodes"); + ExitOnNull(pNodeList, hr, E_FAIL, "selectNodes returned NULL"); + + // Get match-count + hr = pNodeList->get_length(&nodeCount); + ExitOnFailure(hr, "Failed to get node count"); + + // Validate with request match parameter + switch (eMatch) + { + case first: + maxMatches = min(1, nodeCount); + break; + case all: + maxMatches = nodeCount; + break; + case enforceSingle: + if (nodeCount != 1) + { + hr = E_INVALIDARG; + ExitOnFailure(hr, "XmlSreach %i matches. Expected exactly one match", nodeCount); + } + maxMatches = 1; + break; + default: + hr = E_INVALIDARG; + ExitOnFailure(hr, "Wrong match parameter for XmlSreach."); + break; + } + + if (maxMatches == 0) + { + WcaLog(LOGLEVEL::LOGMSG_STANDARD, "No matches found"); + ExitFunction(); + } + + for (LONG i = 0; i < maxMatches; ++i) + { + CComPtr pNode; + CComVariant nodeValue; + + hr = pNodeList->get_item(i, &pNode); + ExitOnFailure(hr, "Failed to get node."); + ExitOnNull(pNode.p, hr, E_FAIL, "Failed to get node."); + + hr = pNode->get_nodeValue(&nodeValue); + ExitOnFailure(hr, "Failed to get node's value."); + + hr = nodeValue.ChangeType(VT_BSTR); + ExitOnFailure(hr, "Failed to get node's value as string."); + + // Add result + hr = result.AppendBSTR(nodeValue.bstrVal); + ExitOnFailure(hr, "Failed to append result."); + + // Add delimiter (unless this is the last) + if (i < maxMatches - 1) + { + hr = result.AppendBSTR(delimiter); + ExitOnFailure(hr, "Failed to append delimiter."); + } + } + + // Put in property + hr = WcaSetProperty(pProperty, (LPWSTR)result); + } + catch (CAtlException ex) + { + hr = (HRESULT)ex; + ExitOnFailure(hr, "Failed querying XML"); + } + catch (...) + { + hr = E_FAIL; + ExitOnFailure(hr, "Failed querying XML"); + } + +LExit: + return hr; +} diff --git a/PanelSwCustomActions/XslTransform.cpp b/src/PanelSwCustomActions/XslTransform.cpp similarity index 100% rename from PanelSwCustomActions/XslTransform.cpp rename to src/PanelSwCustomActions/XslTransform.cpp diff --git a/PanelSwCustomActions/XslTransform.h b/src/PanelSwCustomActions/XslTransform.h similarity index 100% rename from PanelSwCustomActions/XslTransform.h rename to src/PanelSwCustomActions/XslTransform.h diff --git a/PanelSwCustomActions/framework.h b/src/PanelSwCustomActions/framework.h similarity index 100% rename from PanelSwCustomActions/framework.h rename to src/PanelSwCustomActions/framework.h diff --git a/PanelSwCustomActions/pch.cpp b/src/PanelSwCustomActions/pch.cpp similarity index 100% rename from PanelSwCustomActions/pch.cpp rename to src/PanelSwCustomActions/pch.cpp diff --git a/PanelSwCustomActions/pch.h b/src/PanelSwCustomActions/pch.h similarity index 100% rename from PanelSwCustomActions/pch.h rename to src/PanelSwCustomActions/pch.h diff --git a/PanelSwWixExtension.sln b/src/PanelSwWixExtension.sln old mode 100755 new mode 100644 similarity index 98% rename from PanelSwWixExtension.sln rename to src/PanelSwWixExtension.sln index 0987da08..4ceb4c20 --- a/PanelSwWixExtension.sln +++ b/src/PanelSwWixExtension.sln @@ -1,718 +1,718 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.1.32421.90 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "PanelSwWixLib", "wixlib\PanelSwWixLib.wixproj", "{B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}" - ProjectSection(ProjectDependencies) = postProject - {0C3A56AA-8073-44E1-8DE4-C257D581BFF0} = {0C3A56AA-8073-44E1-8DE4-C257D581BFF0} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PanelSwWixExtension", "PanelSwWixExtension\PanelSwWixExtension.csproj", "{69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}" - ProjectSection(ProjectDependencies) = postProject - {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE} = {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PanelSwCustomActions", "PanelSwCustomActions\PanelSwCustomActions.vcxproj", "{0C3A56AA-8073-44E1-8DE4-C257D581BFF0}" - ProjectSection(ProjectDependencies) = postProject - {7C6B230A-9186-4C1E-B61D-E803CC36A347} = {7C6B230A-9186-4C1E-B61D-E803CC36A347} - {46D02BC4-720A-4B33-AA27-4103E7349F02} = {46D02BC4-720A-4B33-AA27-4103E7349F02} - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnitTests", "UnitTests", "{B533D9FC-4927-4A05-892D-B90E8BEDCF5D}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ReadIniValuesUT", "UnitTests\ReadIniValuesUT\ReadIniValuesUT.wixproj", "{EEC5D4C5-9873-42E1-8A7F-79DB5314592B}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "CustomUninstallKeyUT", "UnitTests\CustomUninstallKeyUT\CustomUninstallKeyUT.wixproj", "{5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "RemoveRegistryValueUT", "UnitTests\RemoveRegistryValueUT\RemoveRegistryValueUT.wixproj", "{301175D9-93BD-49D2-8AE2-31693630372C}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "XmlSearchUT", "UnitTests\XmlSearchUT\XmlSearchUT.wixproj", "{0631B7FA-D5A5-4B4B-8289-E0415420D6C7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CaCommon", "CaCommon\CaCommon.vcxproj", "{7C6B230A-9186-4C1E-B61D-E803CC36A347}" - ProjectSection(ProjectDependencies) = postProject - {46D02BC4-720A-4B33-AA27-4103E7349F02} = {46D02BC4-720A-4B33-AA27-4103E7349F02} - EndProjectSection -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "TelemetryUT", "UnitTests\TelemetryUT\TelemetryUT.wixproj", "{12C34100-BC94-48E7-AE28-8B62CAD23155}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "MsiSqlQueryUT", "UnitTests\MsiSqlQueryUT\MsiSqlQueryUT.wixproj", "{9831ED5E-E812-484B-BDCF-AB27ED9297F6}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "RegexUT", "UnitTests\RegexUT\RegexUT.wixproj", "{738E0950-AD2F-49B0-A791-94E7E011E233}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "FileOperationsUT", "UnitTests\FileOperationsUT\FileOperationsUT.wixproj", "{2B87572F-9B38-4F39-A213-97C1AC64703E}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "TaskScheulerUT", "UnitTests\TaskScheulerUT\TaskScheulerUT.wixproj", "{31F20547-2522-4643-AE23-B5B4E25A8852}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{096EB3BA-5DCA-4121-8407-C93F31997339}" - ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - .github\workflows\codeql-analysis.yml = .github\workflows\codeql-analysis.yml - Directory.Build.props = Directory.Build.props - Directory.Packages.props = Directory.Packages.props - dirs.proj = dirs.proj - .github\workflows\github-actions-build.yml = .github\workflows\github-actions-build.yml - global.json = global.json - LICENSE.md = LICENSE.md - nuget.config = nuget.config - Nuget\PanelSwWixExtension4.props = Nuget\PanelSwWixExtension4.props - Nuget\PanelSwWixExtension4.targets = Nuget\PanelSwWixExtension4.targets - .github\workflows\publish-build.yml = .github\workflows\publish-build.yml - README.md = README.md - TidyBuild.custom.props = TidyBuild.custom.props - TidyBuild.custom.targets = TidyBuild.custom.targets - TidyBuild.user.props = TidyBuild.user.props - EndProjectSection -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ExecOnComponentUT", "UnitTests\ExecOnComponentUT\ExecOnComponentUT.wixproj", "{80C0972A-EB37-4DF3-95DB-704EB7F7965C}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "DismUT", "UnitTests\DismUT\DismUT.wixproj", "{E9A9526B-0AD2-4DE2-A154-6558B99A4287}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PswManagedCA", "PswManagedCA\PswManagedCA.csproj", "{EEC82796-3809-4D8B-9F2B-D9F1DB044E39}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ZipFileUT", "UnitTests\ZipFileUT\ZipFileUT.wixproj", "{272D736A-5479-4915-B8FE-5A0D908AB61F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Dism", "Dism\Dism.vcxproj", "{E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ServiceConfigUT", "UnitTests\ServiceConfigUT\ServiceConfigUT.wixproj", "{C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "CleanPendingFileRenameOperationsUT", "UnitTests\CleanPendingFileRenameOperationsUT\CleanPendingFileRenameOperationsUT.wixproj", "{EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "InstallUtilUT", "UnitTests\InstallUtilUT\InstallUtilUT.wixproj", "{7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "SqlSearchUT", "UnitTests\SqlSearchUT\SqlSearchUT.wixproj", "{4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "BackupAndRestoreUT", "UnitTests\BackupAndRestoreUT\BackupAndRestoreUT.wixproj", "{21F86B1E-9F55-4CC8-93C7-BD237157B7F5}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "CreateSelfSignCertificateUT", "UnitTests\CreateSelfSignCertificateUT\CreateSelfSignCertificateUT.wixproj", "{95697A34-1519-42EC-A96B-3090AE6EAE2A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProtoCaLib", "ProtoCaLib\ProtoCaLib.vcxproj", "{46D02BC4-720A-4B33-AA27-4103E7349F02}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SetPropertyFromPipeBAF", "UnitTests\SetPropertyFromPipe\SetPropertyFromPipeBAF\SetPropertyFromPipeBAF.vcxproj", "{EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "SetPropertyFromPipeBootstrapper", "UnitTests\SetPropertyFromPipe\SetPropertyFromPipeBootstrapper\SetPropertyFromPipeBootstrapper.wixproj", "{F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "SetPropertyFromPipeSetup", "UnitTests\SetPropertyFromPipe\SetPropertyFromPipeSetup\SetPropertyFromPipeSetup.wixproj", "{C3F36939-174F-4A7C-880E-B25875B7ABDC}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "EvaluateExpressionUT", "UnitTests\EvaluateExpressionUT\EvaluateExpressionUT.wixproj", "{CBA21767-A300-4048-BCD4-4757F6FD0BEA}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "DiskSpaceUT", "UnitTests\DiskSpaceUT\DiskSpaceUT.wixproj", "{58646CCF-55D2-4131-BCAC-8670D372BA83}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "JsonJPathUT", "UnitTests\JsonJPathUT\JsonJPathUT.wixproj", "{CF761D68-A8DE-41F3-8888-91B0C70B2C8E}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "AccountNamesUT", "UnitTests\AccountNamesUT\AccountNamesUT.wixproj", "{49D91747-0876-4315-AD43-089EAC141670}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "AccountSidSearchUT", "UnitTests\AccountSidSearchUT\AccountSidSearchUT.wixproj", "{9373BDEE-4179-45BD-BA91-467C37729852}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ForceVersionUT", "UnitTests\ForceVersionUT\ForceVersionUT.wixproj", "{F773F85B-CD8B-4FDD-ABFC-B74C018AB900}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "WebsiteConfigUT", "UnitTests\WebsiteConfigUT\WebsiteConfigUT.wixproj", "{742496FF-76A2-419C-BA48-BE8C6C1C23EB}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "VersionCompareUT", "UnitTests\VersionCompareUT\VersionCompareUT.wixproj", "{E386BD7E-2DDC-4F30-8FD0-2ED41E851159}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "PathSearchUT", "UnitTests\PathSearchUT\PathSearchUT.wixproj", "{0FBEE09F-52C0-4AA2-8238-D55067106829}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "CustomActionDataUT", "UnitTests\CustomActionDataUT\CustomActionDataUT.wixproj", "{F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "StringUT", "UnitTests\StringUT\StringUT.wixproj", "{60408F7C-8FEB-4F24-A437-6DE8850223AB}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "WmiSearchUT", "UnitTests\WmiSearchUT\WmiSearchUT.wixproj", "{426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "RestartLocalResourcesUT", "UnitTests\RestartLocalResourcesUT\RestartLocalResourcesUT.wixproj", "{71CA675A-453F-4756-924F-CD36C6C162E8}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "Md5HashUT", "UnitTests\Md5HashUT\Md5HashUT.wixproj", "{42520F9E-9D2A-4FD8-B747-2CC03120F588}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "SplitFileUT", "UnitTests\SplitFileUT\SplitFileUT.wixproj", "{1C727FB4-460C-4EDA-B751-0593E2910B4C}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "PreprocessorUT", "UnitTests\PreprocessorUT\PreprocessorUT.wixproj", "{9D192FCB-1D43-4DA7-902E-8076E757A045}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "PayloadUT", "UnitTests\PayloadUT\PayloadUT.wixproj", "{D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PanelSwWixHarvestExtension", "PanelSwWixHarvestExtension\PanelSwWixHarvestExtension.csproj", "{3463E375-46E1-46DD-9AF4-8E925F581B93}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "PromptFileDowngradesUT", "UnitTests\PromptFileDowngradesUT\PromptFileDowngradesUT.wixproj", "{1C35A94C-5A83-49BB-A855-D052F0B0BFB4}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "HeatExtUT", "UnitTests\HeatExtUT\HeatExtUT.wixproj", "{EBB376C5-D953-405D-BFA5-1E50FD10F419}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DeferredExePackage", "DeferredExePackage\DeferredExePackage.vcxproj", "{B729FB3C-25CF-4216-940D-69EA78779CD7}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "IsWindowsVersionOrGreaterUT", "UnitTests\IsWindowsVersionOrGreaterUT\IsWindowsVersionOrGreaterUT.wixproj", "{E4D1FCE8-9273-47DE-A672-209F010F74B7}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ListProcessorFeaturesUT", "UnitTests\ListProcessorFeaturesUT\ListProcessorFeaturesUT.wixproj", "{DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ExecuteCommandUT", "UnitTests\ExecuteCommandUT\ExecuteCommandUT.wixproj", "{A01CBD4F-7229-4B71-8657-7683C98BCB7C}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "DuplicateFolderUT", "UnitTests\DuplicateFolderUT\DuplicateFolderUT.wixproj", "{5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}" -EndProject -Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ContainerTemplateUT", "UnitTests\ContainerTemplateUT\ContainerTemplateUT.wixproj", "{7BB9BAE3-93F4-47AD-A630-E0FE147F3026}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PanelSwBackendExtension", "PanelSwBackendExtension\PanelSwBackendExtension.vcxproj", "{6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM64 = Debug|ARM64 - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|ARM64 = Release|ARM64 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Debug|ARM64.ActiveCfg = Debug|x86 - {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Debug|ARM64.Build.0 = Debug|x86 - {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Debug|x64.ActiveCfg = Debug|x64 - {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Debug|x64.Build.0 = Debug|x64 - {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Debug|x86.ActiveCfg = Release|x86 - {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Debug|x86.Build.0 = Release|x86 - {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Release|ARM64.ActiveCfg = Release|x86 - {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Release|ARM64.Build.0 = Release|x86 - {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Release|x64.ActiveCfg = Release|x64 - {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Release|x64.Build.0 = Release|x64 - {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Release|x86.ActiveCfg = Release|x86 - {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Release|x86.Build.0 = Release|x86 - {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Debug|ARM64.Build.0 = Debug|Any CPU - {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Debug|x64.ActiveCfg = Debug|Any CPU - {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Debug|x64.Build.0 = Debug|Any CPU - {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Debug|x86.ActiveCfg = Debug|Any CPU - {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Debug|x86.Build.0 = Debug|Any CPU - {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Release|ARM64.ActiveCfg = Release|Any CPU - {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Release|ARM64.Build.0 = Release|Any CPU - {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Release|x64.ActiveCfg = Release|Any CPU - {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Release|x64.Build.0 = Release|Any CPU - {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Release|x86.ActiveCfg = Release|Any CPU - {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Release|x86.Build.0 = Release|Any CPU - {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Debug|ARM64.ActiveCfg = Release|Win32 - {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Debug|ARM64.Build.0 = Release|Win32 - {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Debug|x64.ActiveCfg = Release|Win32 - {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Debug|x64.Build.0 = Release|Win32 - {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Debug|x86.ActiveCfg = Release|Win32 - {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Debug|x86.Build.0 = Release|Win32 - {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Release|ARM64.ActiveCfg = Release|ARM64 - {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Release|ARM64.Build.0 = Release|ARM64 - {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Release|x64.ActiveCfg = Release|Win32 - {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Release|x64.Build.0 = Release|Win32 - {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Release|x86.ActiveCfg = Release|Win32 - {EEC5D4C5-9873-42E1-8A7F-79DB5314592B}.Debug|ARM64.ActiveCfg = Release|x86 - {EEC5D4C5-9873-42E1-8A7F-79DB5314592B}.Debug|x64.ActiveCfg = Debug|x64 - {EEC5D4C5-9873-42E1-8A7F-79DB5314592B}.Debug|x64.Build.0 = Debug|x64 - {EEC5D4C5-9873-42E1-8A7F-79DB5314592B}.Debug|x86.ActiveCfg = Release|x86 - {EEC5D4C5-9873-42E1-8A7F-79DB5314592B}.Release|ARM64.ActiveCfg = Release|x86 - {EEC5D4C5-9873-42E1-8A7F-79DB5314592B}.Release|x64.ActiveCfg = Release|x64 - {EEC5D4C5-9873-42E1-8A7F-79DB5314592B}.Release|x64.Build.0 = Release|x64 - {EEC5D4C5-9873-42E1-8A7F-79DB5314592B}.Release|x86.ActiveCfg = Release|x86 - {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}.Debug|ARM64.ActiveCfg = Release|x86 - {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}.Debug|x64.ActiveCfg = Debug|x64 - {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}.Debug|x64.Build.0 = Debug|x64 - {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}.Debug|x86.ActiveCfg = Release|x86 - {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}.Release|ARM64.ActiveCfg = Release|x86 - {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}.Release|x64.ActiveCfg = Release|x64 - {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}.Release|x64.Build.0 = Release|x64 - {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}.Release|x86.ActiveCfg = Release|x86 - {301175D9-93BD-49D2-8AE2-31693630372C}.Debug|ARM64.ActiveCfg = Release|x86 - {301175D9-93BD-49D2-8AE2-31693630372C}.Debug|x64.ActiveCfg = Debug|x64 - {301175D9-93BD-49D2-8AE2-31693630372C}.Debug|x64.Build.0 = Debug|x64 - {301175D9-93BD-49D2-8AE2-31693630372C}.Debug|x86.ActiveCfg = Release|x86 - {301175D9-93BD-49D2-8AE2-31693630372C}.Release|ARM64.ActiveCfg = Release|x86 - {301175D9-93BD-49D2-8AE2-31693630372C}.Release|x64.ActiveCfg = Release|x64 - {301175D9-93BD-49D2-8AE2-31693630372C}.Release|x64.Build.0 = Release|x64 - {301175D9-93BD-49D2-8AE2-31693630372C}.Release|x86.ActiveCfg = Release|x86 - {0631B7FA-D5A5-4B4B-8289-E0415420D6C7}.Debug|ARM64.ActiveCfg = Release|x86 - {0631B7FA-D5A5-4B4B-8289-E0415420D6C7}.Debug|x64.ActiveCfg = Debug|x64 - {0631B7FA-D5A5-4B4B-8289-E0415420D6C7}.Debug|x64.Build.0 = Debug|x64 - {0631B7FA-D5A5-4B4B-8289-E0415420D6C7}.Debug|x86.ActiveCfg = Release|x86 - {0631B7FA-D5A5-4B4B-8289-E0415420D6C7}.Release|ARM64.ActiveCfg = Release|x86 - {0631B7FA-D5A5-4B4B-8289-E0415420D6C7}.Release|x64.ActiveCfg = Release|x64 - {0631B7FA-D5A5-4B4B-8289-E0415420D6C7}.Release|x64.Build.0 = Release|x64 - {0631B7FA-D5A5-4B4B-8289-E0415420D6C7}.Release|x86.ActiveCfg = Release|x86 - {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Debug|ARM64.ActiveCfg = Release|Win32 - {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Debug|x64.ActiveCfg = Release|Win32 - {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Debug|x64.Build.0 = Release|Win32 - {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Debug|x86.ActiveCfg = Release|Win32 - {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Release|ARM64.ActiveCfg = Release|ARM64 - {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Release|ARM64.Build.0 = Release|ARM64 - {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Release|x64.ActiveCfg = Release|Win32 - {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Release|x64.Build.0 = Release|Win32 - {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Release|x86.ActiveCfg = Release|Win32 - {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Release|x86.Build.0 = Release|Win32 - {12C34100-BC94-48E7-AE28-8B62CAD23155}.Debug|ARM64.ActiveCfg = Release|x86 - {12C34100-BC94-48E7-AE28-8B62CAD23155}.Debug|x64.ActiveCfg = Debug|x64 - {12C34100-BC94-48E7-AE28-8B62CAD23155}.Debug|x64.Build.0 = Debug|x64 - {12C34100-BC94-48E7-AE28-8B62CAD23155}.Debug|x86.ActiveCfg = Release|x86 - {12C34100-BC94-48E7-AE28-8B62CAD23155}.Release|ARM64.ActiveCfg = Release|x86 - {12C34100-BC94-48E7-AE28-8B62CAD23155}.Release|x64.ActiveCfg = Release|x64 - {12C34100-BC94-48E7-AE28-8B62CAD23155}.Release|x64.Build.0 = Release|x64 - {12C34100-BC94-48E7-AE28-8B62CAD23155}.Release|x86.ActiveCfg = Release|x86 - {9831ED5E-E812-484B-BDCF-AB27ED9297F6}.Debug|ARM64.ActiveCfg = Release|x86 - {9831ED5E-E812-484B-BDCF-AB27ED9297F6}.Debug|x64.ActiveCfg = Debug|x64 - {9831ED5E-E812-484B-BDCF-AB27ED9297F6}.Debug|x64.Build.0 = Debug|x64 - {9831ED5E-E812-484B-BDCF-AB27ED9297F6}.Debug|x86.ActiveCfg = Release|x86 - {9831ED5E-E812-484B-BDCF-AB27ED9297F6}.Release|ARM64.ActiveCfg = Release|x86 - {9831ED5E-E812-484B-BDCF-AB27ED9297F6}.Release|x64.ActiveCfg = Release|x64 - {9831ED5E-E812-484B-BDCF-AB27ED9297F6}.Release|x64.Build.0 = Release|x64 - {9831ED5E-E812-484B-BDCF-AB27ED9297F6}.Release|x86.ActiveCfg = Release|x86 - {738E0950-AD2F-49B0-A791-94E7E011E233}.Debug|ARM64.ActiveCfg = Release|x86 - {738E0950-AD2F-49B0-A791-94E7E011E233}.Debug|x64.ActiveCfg = Debug|x64 - {738E0950-AD2F-49B0-A791-94E7E011E233}.Debug|x64.Build.0 = Debug|x64 - {738E0950-AD2F-49B0-A791-94E7E011E233}.Debug|x86.ActiveCfg = Release|x86 - {738E0950-AD2F-49B0-A791-94E7E011E233}.Release|ARM64.ActiveCfg = Release|x86 - {738E0950-AD2F-49B0-A791-94E7E011E233}.Release|x64.ActiveCfg = Release|x64 - {738E0950-AD2F-49B0-A791-94E7E011E233}.Release|x64.Build.0 = Release|x64 - {738E0950-AD2F-49B0-A791-94E7E011E233}.Release|x86.ActiveCfg = Release|x86 - {2B87572F-9B38-4F39-A213-97C1AC64703E}.Debug|ARM64.ActiveCfg = Release|x86 - {2B87572F-9B38-4F39-A213-97C1AC64703E}.Debug|x64.ActiveCfg = Debug|x64 - {2B87572F-9B38-4F39-A213-97C1AC64703E}.Debug|x64.Build.0 = Debug|x64 - {2B87572F-9B38-4F39-A213-97C1AC64703E}.Debug|x86.ActiveCfg = Release|x86 - {2B87572F-9B38-4F39-A213-97C1AC64703E}.Release|ARM64.ActiveCfg = Release|x86 - {2B87572F-9B38-4F39-A213-97C1AC64703E}.Release|x64.ActiveCfg = Release|x64 - {2B87572F-9B38-4F39-A213-97C1AC64703E}.Release|x64.Build.0 = Release|x64 - {2B87572F-9B38-4F39-A213-97C1AC64703E}.Release|x86.ActiveCfg = Release|x86 - {31F20547-2522-4643-AE23-B5B4E25A8852}.Debug|ARM64.ActiveCfg = Release|x86 - {31F20547-2522-4643-AE23-B5B4E25A8852}.Debug|x64.ActiveCfg = Debug|x64 - {31F20547-2522-4643-AE23-B5B4E25A8852}.Debug|x64.Build.0 = Debug|x64 - {31F20547-2522-4643-AE23-B5B4E25A8852}.Debug|x86.ActiveCfg = Release|x86 - {31F20547-2522-4643-AE23-B5B4E25A8852}.Release|ARM64.ActiveCfg = Release|x86 - {31F20547-2522-4643-AE23-B5B4E25A8852}.Release|x64.ActiveCfg = Release|x64 - {31F20547-2522-4643-AE23-B5B4E25A8852}.Release|x64.Build.0 = Release|x64 - {31F20547-2522-4643-AE23-B5B4E25A8852}.Release|x86.ActiveCfg = Release|x86 - {80C0972A-EB37-4DF3-95DB-704EB7F7965C}.Debug|ARM64.ActiveCfg = Release|x86 - {80C0972A-EB37-4DF3-95DB-704EB7F7965C}.Debug|x64.ActiveCfg = Debug|x64 - {80C0972A-EB37-4DF3-95DB-704EB7F7965C}.Debug|x64.Build.0 = Debug|x64 - {80C0972A-EB37-4DF3-95DB-704EB7F7965C}.Debug|x86.ActiveCfg = Release|x86 - {80C0972A-EB37-4DF3-95DB-704EB7F7965C}.Release|ARM64.ActiveCfg = Release|x86 - {80C0972A-EB37-4DF3-95DB-704EB7F7965C}.Release|x64.ActiveCfg = Release|x64 - {80C0972A-EB37-4DF3-95DB-704EB7F7965C}.Release|x64.Build.0 = Release|x64 - {80C0972A-EB37-4DF3-95DB-704EB7F7965C}.Release|x86.ActiveCfg = Release|x86 - {E9A9526B-0AD2-4DE2-A154-6558B99A4287}.Debug|ARM64.ActiveCfg = Release|x86 - {E9A9526B-0AD2-4DE2-A154-6558B99A4287}.Debug|x64.ActiveCfg = Debug|x64 - {E9A9526B-0AD2-4DE2-A154-6558B99A4287}.Debug|x64.Build.0 = Debug|x64 - {E9A9526B-0AD2-4DE2-A154-6558B99A4287}.Debug|x86.ActiveCfg = Release|x86 - {E9A9526B-0AD2-4DE2-A154-6558B99A4287}.Release|ARM64.ActiveCfg = Release|x86 - {E9A9526B-0AD2-4DE2-A154-6558B99A4287}.Release|x64.ActiveCfg = Release|x64 - {E9A9526B-0AD2-4DE2-A154-6558B99A4287}.Release|x64.Build.0 = Release|x64 - {E9A9526B-0AD2-4DE2-A154-6558B99A4287}.Release|x86.ActiveCfg = Release|x86 - {EEC82796-3809-4D8B-9F2B-D9F1DB044E39}.Debug|ARM64.ActiveCfg = Release|x86 - {EEC82796-3809-4D8B-9F2B-D9F1DB044E39}.Debug|x64.ActiveCfg = Debug|x64 - {EEC82796-3809-4D8B-9F2B-D9F1DB044E39}.Debug|x64.Build.0 = Debug|x64 - {EEC82796-3809-4D8B-9F2B-D9F1DB044E39}.Debug|x86.ActiveCfg = Release|x86 - {EEC82796-3809-4D8B-9F2B-D9F1DB044E39}.Release|ARM64.ActiveCfg = Release|x86 - {EEC82796-3809-4D8B-9F2B-D9F1DB044E39}.Release|x64.ActiveCfg = Release|x64 - {EEC82796-3809-4D8B-9F2B-D9F1DB044E39}.Release|x64.Build.0 = Release|x64 - {EEC82796-3809-4D8B-9F2B-D9F1DB044E39}.Release|x86.ActiveCfg = Release|x86 - {272D736A-5479-4915-B8FE-5A0D908AB61F}.Debug|ARM64.ActiveCfg = Release|x86 - {272D736A-5479-4915-B8FE-5A0D908AB61F}.Debug|x64.ActiveCfg = Debug|x64 - {272D736A-5479-4915-B8FE-5A0D908AB61F}.Debug|x64.Build.0 = Debug|x64 - {272D736A-5479-4915-B8FE-5A0D908AB61F}.Debug|x86.ActiveCfg = Release|x86 - {272D736A-5479-4915-B8FE-5A0D908AB61F}.Release|ARM64.ActiveCfg = Release|x86 - {272D736A-5479-4915-B8FE-5A0D908AB61F}.Release|x64.ActiveCfg = Release|x64 - {272D736A-5479-4915-B8FE-5A0D908AB61F}.Release|x64.Build.0 = Release|x64 - {272D736A-5479-4915-B8FE-5A0D908AB61F}.Release|x86.ActiveCfg = Release|x86 - {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Debug|ARM64.ActiveCfg = Release|Win32 - {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Debug|ARM64.Build.0 = Release|Win32 - {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Debug|x64.ActiveCfg = Release|x64 - {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Debug|x64.Build.0 = Release|x64 - {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Debug|x86.ActiveCfg = Release|Win32 - {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Debug|x86.Build.0 = Release|Win32 - {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Release|ARM64.ActiveCfg = Release|Win32 - {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Release|x64.ActiveCfg = Release|x64 - {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Release|x64.Build.0 = Release|x64 - {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Release|x86.ActiveCfg = Release|Win32 - {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}.Debug|ARM64.ActiveCfg = Release|x86 - {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}.Debug|x64.ActiveCfg = Debug|x64 - {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}.Debug|x64.Build.0 = Debug|x64 - {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}.Debug|x86.ActiveCfg = Release|x86 - {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}.Release|ARM64.ActiveCfg = Release|x86 - {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}.Release|x64.ActiveCfg = Release|x64 - {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}.Release|x64.Build.0 = Release|x64 - {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}.Release|x86.ActiveCfg = Release|x86 - {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}.Debug|ARM64.ActiveCfg = Release|x86 - {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}.Debug|x64.ActiveCfg = Debug|x64 - {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}.Debug|x64.Build.0 = Debug|x64 - {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}.Debug|x86.ActiveCfg = Release|x86 - {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}.Release|ARM64.ActiveCfg = Release|x86 - {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}.Release|x64.ActiveCfg = Release|x64 - {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}.Release|x64.Build.0 = Release|x64 - {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}.Release|x86.ActiveCfg = Release|x86 - {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}.Debug|ARM64.ActiveCfg = Release|x86 - {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}.Debug|x64.ActiveCfg = Debug|x64 - {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}.Debug|x64.Build.0 = Debug|x64 - {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}.Debug|x86.ActiveCfg = Release|x86 - {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}.Release|ARM64.ActiveCfg = Release|x86 - {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}.Release|x64.ActiveCfg = Release|x64 - {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}.Release|x64.Build.0 = Release|x64 - {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}.Release|x86.ActiveCfg = Release|x86 - {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}.Debug|ARM64.ActiveCfg = Release|x86 - {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}.Debug|x64.ActiveCfg = Debug|x64 - {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}.Debug|x64.Build.0 = Debug|x64 - {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}.Debug|x86.ActiveCfg = Release|x86 - {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}.Release|ARM64.ActiveCfg = Release|x86 - {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}.Release|x64.ActiveCfg = Release|x64 - {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}.Release|x64.Build.0 = Release|x64 - {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}.Release|x86.ActiveCfg = Release|x86 - {21F86B1E-9F55-4CC8-93C7-BD237157B7F5}.Debug|ARM64.ActiveCfg = Release|x86 - {21F86B1E-9F55-4CC8-93C7-BD237157B7F5}.Debug|x64.ActiveCfg = Debug|x64 - {21F86B1E-9F55-4CC8-93C7-BD237157B7F5}.Debug|x64.Build.0 = Debug|x64 - {21F86B1E-9F55-4CC8-93C7-BD237157B7F5}.Debug|x86.ActiveCfg = Release|x86 - {21F86B1E-9F55-4CC8-93C7-BD237157B7F5}.Release|ARM64.ActiveCfg = Release|x86 - {21F86B1E-9F55-4CC8-93C7-BD237157B7F5}.Release|x64.ActiveCfg = Release|x64 - {21F86B1E-9F55-4CC8-93C7-BD237157B7F5}.Release|x64.Build.0 = Release|x64 - {21F86B1E-9F55-4CC8-93C7-BD237157B7F5}.Release|x86.ActiveCfg = Release|x86 - {95697A34-1519-42EC-A96B-3090AE6EAE2A}.Debug|ARM64.ActiveCfg = Release|x86 - {95697A34-1519-42EC-A96B-3090AE6EAE2A}.Debug|x64.ActiveCfg = Debug|x64 - {95697A34-1519-42EC-A96B-3090AE6EAE2A}.Debug|x64.Build.0 = Debug|x64 - {95697A34-1519-42EC-A96B-3090AE6EAE2A}.Debug|x86.ActiveCfg = Release|x86 - {95697A34-1519-42EC-A96B-3090AE6EAE2A}.Release|ARM64.ActiveCfg = Release|x86 - {95697A34-1519-42EC-A96B-3090AE6EAE2A}.Release|x64.ActiveCfg = Release|x64 - {95697A34-1519-42EC-A96B-3090AE6EAE2A}.Release|x64.Build.0 = Release|x64 - {95697A34-1519-42EC-A96B-3090AE6EAE2A}.Release|x86.ActiveCfg = Release|x86 - {46D02BC4-720A-4B33-AA27-4103E7349F02}.Debug|ARM64.ActiveCfg = Release|Win32 - {46D02BC4-720A-4B33-AA27-4103E7349F02}.Debug|x64.ActiveCfg = Release|Win32 - {46D02BC4-720A-4B33-AA27-4103E7349F02}.Debug|x64.Build.0 = Release|Win32 - {46D02BC4-720A-4B33-AA27-4103E7349F02}.Debug|x86.ActiveCfg = Release|Win32 - {46D02BC4-720A-4B33-AA27-4103E7349F02}.Release|ARM64.ActiveCfg = Release|ARM64 - {46D02BC4-720A-4B33-AA27-4103E7349F02}.Release|ARM64.Build.0 = Release|ARM64 - {46D02BC4-720A-4B33-AA27-4103E7349F02}.Release|x64.ActiveCfg = Release|Win32 - {46D02BC4-720A-4B33-AA27-4103E7349F02}.Release|x64.Build.0 = Release|Win32 - {46D02BC4-720A-4B33-AA27-4103E7349F02}.Release|x86.ActiveCfg = Release|Win32 - {46D02BC4-720A-4B33-AA27-4103E7349F02}.Release|x86.Build.0 = Release|Win32 - {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Debug|ARM64.ActiveCfg = Release|Win32 - {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Debug|x64.ActiveCfg = Release|Win32 - {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Debug|x64.Build.0 = Release|Win32 - {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Debug|x86.ActiveCfg = Release|Win32 - {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Release|ARM64.ActiveCfg = Release|Win32 - {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Release|x64.ActiveCfg = Release|Win32 - {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Release|x64.Build.0 = Release|Win32 - {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Release|x86.ActiveCfg = Release|Win32 - {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}.Debug|ARM64.ActiveCfg = Release|x86 - {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}.Debug|x64.ActiveCfg = Debug|x64 - {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}.Debug|x64.Build.0 = Debug|x64 - {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}.Debug|x86.ActiveCfg = Release|x86 - {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}.Release|ARM64.ActiveCfg = Release|x86 - {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}.Release|x64.ActiveCfg = Release|x64 - {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}.Release|x64.Build.0 = Release|x64 - {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}.Release|x86.ActiveCfg = Release|x86 - {C3F36939-174F-4A7C-880E-B25875B7ABDC}.Debug|ARM64.ActiveCfg = Release|x86 - {C3F36939-174F-4A7C-880E-B25875B7ABDC}.Debug|x64.ActiveCfg = Debug|x64 - {C3F36939-174F-4A7C-880E-B25875B7ABDC}.Debug|x64.Build.0 = Debug|x64 - {C3F36939-174F-4A7C-880E-B25875B7ABDC}.Debug|x86.ActiveCfg = Release|x86 - {C3F36939-174F-4A7C-880E-B25875B7ABDC}.Release|ARM64.ActiveCfg = Release|x86 - {C3F36939-174F-4A7C-880E-B25875B7ABDC}.Release|x64.ActiveCfg = Release|x64 - {C3F36939-174F-4A7C-880E-B25875B7ABDC}.Release|x64.Build.0 = Release|x64 - {C3F36939-174F-4A7C-880E-B25875B7ABDC}.Release|x86.ActiveCfg = Release|x86 - {CBA21767-A300-4048-BCD4-4757F6FD0BEA}.Debug|ARM64.ActiveCfg = Release|x86 - {CBA21767-A300-4048-BCD4-4757F6FD0BEA}.Debug|x64.ActiveCfg = Debug|x64 - {CBA21767-A300-4048-BCD4-4757F6FD0BEA}.Debug|x64.Build.0 = Debug|x64 - {CBA21767-A300-4048-BCD4-4757F6FD0BEA}.Debug|x86.ActiveCfg = Release|x86 - {CBA21767-A300-4048-BCD4-4757F6FD0BEA}.Release|ARM64.ActiveCfg = Release|x86 - {CBA21767-A300-4048-BCD4-4757F6FD0BEA}.Release|x64.ActiveCfg = Release|x64 - {CBA21767-A300-4048-BCD4-4757F6FD0BEA}.Release|x64.Build.0 = Release|x64 - {CBA21767-A300-4048-BCD4-4757F6FD0BEA}.Release|x86.ActiveCfg = Release|x86 - {58646CCF-55D2-4131-BCAC-8670D372BA83}.Debug|ARM64.ActiveCfg = Release|x86 - {58646CCF-55D2-4131-BCAC-8670D372BA83}.Debug|x64.ActiveCfg = Debug|x64 - {58646CCF-55D2-4131-BCAC-8670D372BA83}.Debug|x64.Build.0 = Debug|x64 - {58646CCF-55D2-4131-BCAC-8670D372BA83}.Debug|x86.ActiveCfg = Release|x86 - {58646CCF-55D2-4131-BCAC-8670D372BA83}.Release|ARM64.ActiveCfg = Release|x86 - {58646CCF-55D2-4131-BCAC-8670D372BA83}.Release|x64.ActiveCfg = Release|x64 - {58646CCF-55D2-4131-BCAC-8670D372BA83}.Release|x64.Build.0 = Release|x64 - {58646CCF-55D2-4131-BCAC-8670D372BA83}.Release|x86.ActiveCfg = Release|x86 - {CF761D68-A8DE-41F3-8888-91B0C70B2C8E}.Debug|ARM64.ActiveCfg = Release|x86 - {CF761D68-A8DE-41F3-8888-91B0C70B2C8E}.Debug|x64.ActiveCfg = Debug|x64 - {CF761D68-A8DE-41F3-8888-91B0C70B2C8E}.Debug|x64.Build.0 = Debug|x64 - {CF761D68-A8DE-41F3-8888-91B0C70B2C8E}.Debug|x86.ActiveCfg = Release|x86 - {CF761D68-A8DE-41F3-8888-91B0C70B2C8E}.Release|ARM64.ActiveCfg = Release|x86 - {CF761D68-A8DE-41F3-8888-91B0C70B2C8E}.Release|x64.ActiveCfg = Release|x64 - {CF761D68-A8DE-41F3-8888-91B0C70B2C8E}.Release|x64.Build.0 = Release|x64 - {CF761D68-A8DE-41F3-8888-91B0C70B2C8E}.Release|x86.ActiveCfg = Release|x86 - {49D91747-0876-4315-AD43-089EAC141670}.Debug|ARM64.ActiveCfg = Release|x86 - {49D91747-0876-4315-AD43-089EAC141670}.Debug|x64.ActiveCfg = Debug|x64 - {49D91747-0876-4315-AD43-089EAC141670}.Debug|x64.Build.0 = Debug|x64 - {49D91747-0876-4315-AD43-089EAC141670}.Debug|x86.ActiveCfg = Release|x86 - {49D91747-0876-4315-AD43-089EAC141670}.Release|ARM64.ActiveCfg = Release|x86 - {49D91747-0876-4315-AD43-089EAC141670}.Release|x64.ActiveCfg = Release|x64 - {49D91747-0876-4315-AD43-089EAC141670}.Release|x64.Build.0 = Release|x64 - {49D91747-0876-4315-AD43-089EAC141670}.Release|x86.ActiveCfg = Release|x86 - {9373BDEE-4179-45BD-BA91-467C37729852}.Debug|ARM64.ActiveCfg = Release|x86 - {9373BDEE-4179-45BD-BA91-467C37729852}.Debug|x64.ActiveCfg = Debug|x64 - {9373BDEE-4179-45BD-BA91-467C37729852}.Debug|x64.Build.0 = Debug|x64 - {9373BDEE-4179-45BD-BA91-467C37729852}.Debug|x86.ActiveCfg = Release|x86 - {9373BDEE-4179-45BD-BA91-467C37729852}.Release|ARM64.ActiveCfg = Release|x86 - {9373BDEE-4179-45BD-BA91-467C37729852}.Release|x64.ActiveCfg = Release|x64 - {9373BDEE-4179-45BD-BA91-467C37729852}.Release|x64.Build.0 = Release|x64 - {9373BDEE-4179-45BD-BA91-467C37729852}.Release|x86.ActiveCfg = Release|x86 - {F773F85B-CD8B-4FDD-ABFC-B74C018AB900}.Debug|ARM64.ActiveCfg = Release|x86 - {F773F85B-CD8B-4FDD-ABFC-B74C018AB900}.Debug|x64.ActiveCfg = Debug|x64 - {F773F85B-CD8B-4FDD-ABFC-B74C018AB900}.Debug|x64.Build.0 = Debug|x64 - {F773F85B-CD8B-4FDD-ABFC-B74C018AB900}.Debug|x86.ActiveCfg = Release|x86 - {F773F85B-CD8B-4FDD-ABFC-B74C018AB900}.Release|ARM64.ActiveCfg = Release|x86 - {F773F85B-CD8B-4FDD-ABFC-B74C018AB900}.Release|x64.ActiveCfg = Release|x64 - {F773F85B-CD8B-4FDD-ABFC-B74C018AB900}.Release|x64.Build.0 = Release|x64 - {F773F85B-CD8B-4FDD-ABFC-B74C018AB900}.Release|x86.ActiveCfg = Release|x86 - {742496FF-76A2-419C-BA48-BE8C6C1C23EB}.Debug|ARM64.ActiveCfg = Release|x86 - {742496FF-76A2-419C-BA48-BE8C6C1C23EB}.Debug|x64.ActiveCfg = Debug|x64 - {742496FF-76A2-419C-BA48-BE8C6C1C23EB}.Debug|x64.Build.0 = Debug|x64 - {742496FF-76A2-419C-BA48-BE8C6C1C23EB}.Debug|x86.ActiveCfg = Release|x86 - {742496FF-76A2-419C-BA48-BE8C6C1C23EB}.Release|ARM64.ActiveCfg = Release|x86 - {742496FF-76A2-419C-BA48-BE8C6C1C23EB}.Release|x64.ActiveCfg = Release|x64 - {742496FF-76A2-419C-BA48-BE8C6C1C23EB}.Release|x64.Build.0 = Release|x64 - {742496FF-76A2-419C-BA48-BE8C6C1C23EB}.Release|x86.ActiveCfg = Release|x86 - {E386BD7E-2DDC-4F30-8FD0-2ED41E851159}.Debug|ARM64.ActiveCfg = Release|x86 - {E386BD7E-2DDC-4F30-8FD0-2ED41E851159}.Debug|x64.ActiveCfg = Debug|x64 - {E386BD7E-2DDC-4F30-8FD0-2ED41E851159}.Debug|x64.Build.0 = Debug|x64 - {E386BD7E-2DDC-4F30-8FD0-2ED41E851159}.Debug|x86.ActiveCfg = Release|x86 - {E386BD7E-2DDC-4F30-8FD0-2ED41E851159}.Release|ARM64.ActiveCfg = Release|x86 - {E386BD7E-2DDC-4F30-8FD0-2ED41E851159}.Release|x64.ActiveCfg = Release|x64 - {E386BD7E-2DDC-4F30-8FD0-2ED41E851159}.Release|x64.Build.0 = Release|x64 - {E386BD7E-2DDC-4F30-8FD0-2ED41E851159}.Release|x86.ActiveCfg = Release|x86 - {0FBEE09F-52C0-4AA2-8238-D55067106829}.Debug|ARM64.ActiveCfg = Release|x86 - {0FBEE09F-52C0-4AA2-8238-D55067106829}.Debug|x64.ActiveCfg = Debug|x64 - {0FBEE09F-52C0-4AA2-8238-D55067106829}.Debug|x64.Build.0 = Debug|x64 - {0FBEE09F-52C0-4AA2-8238-D55067106829}.Debug|x86.ActiveCfg = Release|x86 - {0FBEE09F-52C0-4AA2-8238-D55067106829}.Release|ARM64.ActiveCfg = Release|x86 - {0FBEE09F-52C0-4AA2-8238-D55067106829}.Release|x64.ActiveCfg = Release|x64 - {0FBEE09F-52C0-4AA2-8238-D55067106829}.Release|x64.Build.0 = Release|x64 - {0FBEE09F-52C0-4AA2-8238-D55067106829}.Release|x86.ActiveCfg = Release|x86 - {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}.Debug|ARM64.ActiveCfg = Release|x86 - {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}.Debug|x64.ActiveCfg = Debug|x64 - {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}.Debug|x64.Build.0 = Debug|x64 - {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}.Debug|x86.ActiveCfg = Release|x86 - {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}.Release|ARM64.ActiveCfg = Release|x86 - {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}.Release|x64.ActiveCfg = Release|x64 - {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}.Release|x64.Build.0 = Release|x64 - {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}.Release|x86.ActiveCfg = Release|x86 - {60408F7C-8FEB-4F24-A437-6DE8850223AB}.Debug|ARM64.ActiveCfg = Release|x86 - {60408F7C-8FEB-4F24-A437-6DE8850223AB}.Debug|x64.ActiveCfg = Debug|x64 - {60408F7C-8FEB-4F24-A437-6DE8850223AB}.Debug|x64.Build.0 = Debug|x64 - {60408F7C-8FEB-4F24-A437-6DE8850223AB}.Debug|x86.ActiveCfg = Release|x86 - {60408F7C-8FEB-4F24-A437-6DE8850223AB}.Release|ARM64.ActiveCfg = Release|x86 - {60408F7C-8FEB-4F24-A437-6DE8850223AB}.Release|x64.ActiveCfg = Release|x64 - {60408F7C-8FEB-4F24-A437-6DE8850223AB}.Release|x64.Build.0 = Release|x64 - {60408F7C-8FEB-4F24-A437-6DE8850223AB}.Release|x86.ActiveCfg = Release|x86 - {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}.Debug|ARM64.ActiveCfg = Release|x86 - {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}.Debug|x64.ActiveCfg = Debug|x64 - {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}.Debug|x64.Build.0 = Debug|x64 - {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}.Debug|x86.ActiveCfg = Release|x86 - {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}.Release|ARM64.ActiveCfg = Release|x86 - {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}.Release|x64.ActiveCfg = Release|x64 - {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}.Release|x64.Build.0 = Release|x64 - {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}.Release|x86.ActiveCfg = Release|x86 - {71CA675A-453F-4756-924F-CD36C6C162E8}.Debug|ARM64.ActiveCfg = Release|x86 - {71CA675A-453F-4756-924F-CD36C6C162E8}.Debug|x64.ActiveCfg = Debug|x64 - {71CA675A-453F-4756-924F-CD36C6C162E8}.Debug|x64.Build.0 = Debug|x64 - {71CA675A-453F-4756-924F-CD36C6C162E8}.Debug|x86.ActiveCfg = Release|x86 - {71CA675A-453F-4756-924F-CD36C6C162E8}.Release|ARM64.ActiveCfg = Release|x86 - {71CA675A-453F-4756-924F-CD36C6C162E8}.Release|x64.ActiveCfg = Release|x64 - {71CA675A-453F-4756-924F-CD36C6C162E8}.Release|x64.Build.0 = Release|x64 - {71CA675A-453F-4756-924F-CD36C6C162E8}.Release|x86.ActiveCfg = Release|x86 - {42520F9E-9D2A-4FD8-B747-2CC03120F588}.Debug|ARM64.ActiveCfg = Release|x86 - {42520F9E-9D2A-4FD8-B747-2CC03120F588}.Debug|x64.ActiveCfg = Debug|x64 - {42520F9E-9D2A-4FD8-B747-2CC03120F588}.Debug|x64.Build.0 = Debug|x64 - {42520F9E-9D2A-4FD8-B747-2CC03120F588}.Debug|x86.ActiveCfg = Release|x86 - {42520F9E-9D2A-4FD8-B747-2CC03120F588}.Release|ARM64.ActiveCfg = Release|x86 - {42520F9E-9D2A-4FD8-B747-2CC03120F588}.Release|x64.ActiveCfg = Release|x64 - {42520F9E-9D2A-4FD8-B747-2CC03120F588}.Release|x64.Build.0 = Release|x64 - {42520F9E-9D2A-4FD8-B747-2CC03120F588}.Release|x86.ActiveCfg = Release|x86 - {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Debug|ARM64.ActiveCfg = Debug|x86 - {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Debug|ARM64.Build.0 = Debug|x86 - {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Debug|x64.ActiveCfg = Debug|x64 - {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Debug|x64.Build.0 = Debug|x64 - {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Debug|x86.ActiveCfg = Debug|x86 - {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Debug|x86.Build.0 = Debug|x86 - {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Release|ARM64.ActiveCfg = Release|x86 - {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Release|x64.ActiveCfg = Release|x64 - {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Release|x64.Build.0 = Release|x64 - {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Release|x86.ActiveCfg = Release|x86 - {9D192FCB-1D43-4DA7-902E-8076E757A045}.Debug|ARM64.ActiveCfg = Debug|x86 - {9D192FCB-1D43-4DA7-902E-8076E757A045}.Debug|ARM64.Build.0 = Debug|x86 - {9D192FCB-1D43-4DA7-902E-8076E757A045}.Debug|x64.ActiveCfg = Debug|x64 - {9D192FCB-1D43-4DA7-902E-8076E757A045}.Debug|x64.Build.0 = Debug|x64 - {9D192FCB-1D43-4DA7-902E-8076E757A045}.Debug|x86.ActiveCfg = Debug|x86 - {9D192FCB-1D43-4DA7-902E-8076E757A045}.Debug|x86.Build.0 = Debug|x86 - {9D192FCB-1D43-4DA7-902E-8076E757A045}.Release|ARM64.ActiveCfg = Release|x86 - {9D192FCB-1D43-4DA7-902E-8076E757A045}.Release|x64.ActiveCfg = Release|x64 - {9D192FCB-1D43-4DA7-902E-8076E757A045}.Release|x64.Build.0 = Release|x64 - {9D192FCB-1D43-4DA7-902E-8076E757A045}.Release|x86.ActiveCfg = Release|x86 - {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Debug|ARM64.ActiveCfg = Debug|x86 - {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Debug|ARM64.Build.0 = Debug|x86 - {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Debug|x64.ActiveCfg = Debug|x64 - {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Debug|x64.Build.0 = Debug|x64 - {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Debug|x86.ActiveCfg = Debug|x86 - {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Debug|x86.Build.0 = Debug|x86 - {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Release|ARM64.ActiveCfg = Release|x86 - {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Release|x64.ActiveCfg = Release|x64 - {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Release|x64.Build.0 = Release|x64 - {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Release|x86.ActiveCfg = Release|x86 - {3463E375-46E1-46DD-9AF4-8E925F581B93}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {3463E375-46E1-46DD-9AF4-8E925F581B93}.Debug|ARM64.Build.0 = Debug|Any CPU - {3463E375-46E1-46DD-9AF4-8E925F581B93}.Debug|x64.ActiveCfg = Debug|Any CPU - {3463E375-46E1-46DD-9AF4-8E925F581B93}.Debug|x64.Build.0 = Debug|Any CPU - {3463E375-46E1-46DD-9AF4-8E925F581B93}.Debug|x86.ActiveCfg = Debug|Any CPU - {3463E375-46E1-46DD-9AF4-8E925F581B93}.Debug|x86.Build.0 = Debug|Any CPU - {3463E375-46E1-46DD-9AF4-8E925F581B93}.Release|ARM64.ActiveCfg = Release|Any CPU - {3463E375-46E1-46DD-9AF4-8E925F581B93}.Release|ARM64.Build.0 = Release|Any CPU - {3463E375-46E1-46DD-9AF4-8E925F581B93}.Release|x64.ActiveCfg = Release|Any CPU - {3463E375-46E1-46DD-9AF4-8E925F581B93}.Release|x64.Build.0 = Release|Any CPU - {3463E375-46E1-46DD-9AF4-8E925F581B93}.Release|x86.ActiveCfg = Release|Any CPU - {3463E375-46E1-46DD-9AF4-8E925F581B93}.Release|x86.Build.0 = Release|Any CPU - {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Debug|ARM64.Build.0 = Debug|ARM64 - {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Debug|x64.ActiveCfg = Debug|x64 - {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Debug|x64.Build.0 = Debug|x64 - {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Debug|x86.ActiveCfg = Debug|x86 - {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Debug|x86.Build.0 = Debug|x86 - {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Release|ARM64.ActiveCfg = Release|ARM64 - {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Release|ARM64.Build.0 = Release|ARM64 - {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Release|x64.ActiveCfg = Release|x64 - {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Release|x64.Build.0 = Release|x64 - {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Release|x86.ActiveCfg = Release|x86 - {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Release|x86.Build.0 = Release|x86 - {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Debug|ARM64.Build.0 = Debug|ARM64 - {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Debug|x64.ActiveCfg = Debug|x64 - {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Debug|x64.Build.0 = Debug|x64 - {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Debug|x86.ActiveCfg = Debug|x86 - {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Debug|x86.Build.0 = Debug|x86 - {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Release|ARM64.ActiveCfg = Release|ARM64 - {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Release|ARM64.Build.0 = Release|ARM64 - {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Release|x64.ActiveCfg = Release|x64 - {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Release|x64.Build.0 = Release|x64 - {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Release|x86.ActiveCfg = Release|x86 - {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Release|x86.Build.0 = Release|x86 - {B729FB3C-25CF-4216-940D-69EA78779CD7}.Debug|ARM64.ActiveCfg = Release|ARM64 - {B729FB3C-25CF-4216-940D-69EA78779CD7}.Debug|ARM64.Build.0 = Release|ARM64 - {B729FB3C-25CF-4216-940D-69EA78779CD7}.Debug|x64.ActiveCfg = Release|x64 - {B729FB3C-25CF-4216-940D-69EA78779CD7}.Debug|x64.Build.0 = Release|x64 - {B729FB3C-25CF-4216-940D-69EA78779CD7}.Debug|x86.ActiveCfg = Release|Win32 - {B729FB3C-25CF-4216-940D-69EA78779CD7}.Debug|x86.Build.0 = Release|Win32 - {B729FB3C-25CF-4216-940D-69EA78779CD7}.Release|ARM64.ActiveCfg = Release|ARM64 - {B729FB3C-25CF-4216-940D-69EA78779CD7}.Release|ARM64.Build.0 = Release|ARM64 - {B729FB3C-25CF-4216-940D-69EA78779CD7}.Release|x64.ActiveCfg = Release|x64 - {B729FB3C-25CF-4216-940D-69EA78779CD7}.Release|x64.Build.0 = Release|x64 - {B729FB3C-25CF-4216-940D-69EA78779CD7}.Release|x86.ActiveCfg = Release|Win32 - {B729FB3C-25CF-4216-940D-69EA78779CD7}.Release|x86.Build.0 = Release|Win32 - {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Debug|ARM64.Build.0 = Debug|ARM64 - {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Debug|x64.ActiveCfg = Debug|x64 - {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Debug|x64.Build.0 = Debug|x64 - {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Debug|x86.ActiveCfg = Debug|x86 - {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Debug|x86.Build.0 = Debug|x86 - {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Release|ARM64.ActiveCfg = Release|ARM64 - {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Release|ARM64.Build.0 = Release|ARM64 - {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Release|x64.ActiveCfg = Release|x64 - {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Release|x64.Build.0 = Release|x64 - {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Release|x86.ActiveCfg = Release|x86 - {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Release|x86.Build.0 = Release|x86 - {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Debug|ARM64.ActiveCfg = Debug|x86 - {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Debug|ARM64.Build.0 = Debug|x86 - {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Debug|x64.ActiveCfg = Debug|x86 - {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Debug|x64.Build.0 = Debug|x86 - {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Debug|x86.ActiveCfg = Debug|x86 - {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Debug|x86.Build.0 = Debug|x86 - {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Release|ARM64.ActiveCfg = Release|x86 - {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Release|ARM64.Build.0 = Release|x86 - {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Release|x64.ActiveCfg = Release|x86 - {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Release|x64.Build.0 = Release|x86 - {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Release|x86.ActiveCfg = Release|x86 - {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Release|x86.Build.0 = Release|x86 - {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Debug|ARM64.Build.0 = Debug|ARM64 - {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Debug|x64.ActiveCfg = Debug|x64 - {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Debug|x64.Build.0 = Debug|x64 - {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Debug|x86.ActiveCfg = Debug|x86 - {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Debug|x86.Build.0 = Debug|x86 - {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Release|ARM64.ActiveCfg = Release|ARM64 - {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Release|ARM64.Build.0 = Release|ARM64 - {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Release|x64.ActiveCfg = Release|x64 - {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Release|x64.Build.0 = Release|x64 - {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Release|x86.ActiveCfg = Release|x86 - {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Release|x86.Build.0 = Release|x86 - {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Debug|ARM64.Build.0 = Debug|ARM64 - {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Debug|x64.ActiveCfg = Debug|x64 - {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Debug|x64.Build.0 = Debug|x64 - {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Debug|x86.ActiveCfg = Debug|x86 - {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Debug|x86.Build.0 = Debug|x86 - {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Release|ARM64.ActiveCfg = Release|ARM64 - {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Release|ARM64.Build.0 = Release|ARM64 - {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Release|x64.ActiveCfg = Release|x64 - {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Release|x64.Build.0 = Release|x64 - {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Release|x86.ActiveCfg = Release|x86 - {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Release|x86.Build.0 = Release|x86 - {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Debug|ARM64.Build.0 = Debug|ARM64 - {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Debug|x64.ActiveCfg = Debug|x64 - {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Debug|x64.Build.0 = Debug|x64 - {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Debug|x86.ActiveCfg = Debug|x86 - {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Debug|x86.Build.0 = Debug|x86 - {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Release|ARM64.ActiveCfg = Release|ARM64 - {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Release|ARM64.Build.0 = Release|ARM64 - {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Release|x64.ActiveCfg = Release|x64 - {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Release|x64.Build.0 = Release|x64 - {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Release|x86.ActiveCfg = Release|x86 - {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Release|x86.Build.0 = Release|x86 - {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Debug|ARM64.ActiveCfg = Release|Win32 - {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Debug|ARM64.Build.0 = Release|Win32 - {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Debug|x64.ActiveCfg = Release|Win32 - {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Debug|x64.Build.0 = Release|Win32 - {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Debug|x86.ActiveCfg = Release|Win32 - {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Debug|x86.Build.0 = Release|Win32 - {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Release|ARM64.ActiveCfg = Release|Win32 - {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Release|ARM64.Build.0 = Release|Win32 - {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Release|x64.ActiveCfg = Release|Win32 - {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Release|x64.Build.0 = Release|Win32 - {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Release|x86.ActiveCfg = Release|Win32 - {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {EEC5D4C5-9873-42E1-8A7F-79DB5314592B} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {301175D9-93BD-49D2-8AE2-31693630372C} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {0631B7FA-D5A5-4B4B-8289-E0415420D6C7} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {12C34100-BC94-48E7-AE28-8B62CAD23155} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {9831ED5E-E812-484B-BDCF-AB27ED9297F6} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {738E0950-AD2F-49B0-A791-94E7E011E233} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {2B87572F-9B38-4F39-A213-97C1AC64703E} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {31F20547-2522-4643-AE23-B5B4E25A8852} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {80C0972A-EB37-4DF3-95DB-704EB7F7965C} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {E9A9526B-0AD2-4DE2-A154-6558B99A4287} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {272D736A-5479-4915-B8FE-5A0D908AB61F} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {21F86B1E-9F55-4CC8-93C7-BD237157B7F5} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {95697A34-1519-42EC-A96B-3090AE6EAE2A} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {C3F36939-174F-4A7C-880E-B25875B7ABDC} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {CBA21767-A300-4048-BCD4-4757F6FD0BEA} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {58646CCF-55D2-4131-BCAC-8670D372BA83} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {CF761D68-A8DE-41F3-8888-91B0C70B2C8E} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {49D91747-0876-4315-AD43-089EAC141670} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {9373BDEE-4179-45BD-BA91-467C37729852} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {F773F85B-CD8B-4FDD-ABFC-B74C018AB900} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {742496FF-76A2-419C-BA48-BE8C6C1C23EB} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {E386BD7E-2DDC-4F30-8FD0-2ED41E851159} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {0FBEE09F-52C0-4AA2-8238-D55067106829} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {60408F7C-8FEB-4F24-A437-6DE8850223AB} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {71CA675A-453F-4756-924F-CD36C6C162E8} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {42520F9E-9D2A-4FD8-B747-2CC03120F588} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {1C727FB4-460C-4EDA-B751-0593E2910B4C} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {9D192FCB-1D43-4DA7-902E-8076E757A045} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {1C35A94C-5A83-49BB-A855-D052F0B0BFB4} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {EBB376C5-D953-405D-BFA5-1E50FD10F419} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {E4D1FCE8-9273-47DE-A672-209F010F74B7} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {A01CBD4F-7229-4B71-8657-7683C98BCB7C} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - {7BB9BAE3-93F4-47AD-A630-E0FE147F3026} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {F5B6389D-77ED-4938-A322-8DFCA4D9FEF5} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32421.90 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "PanelSwWixLib", "wixlib\PanelSwWixLib.wixproj", "{B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}" + ProjectSection(ProjectDependencies) = postProject + {0C3A56AA-8073-44E1-8DE4-C257D581BFF0} = {0C3A56AA-8073-44E1-8DE4-C257D581BFF0} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PanelSwWixExtension", "PanelSwWixExtension\PanelSwWixExtension.csproj", "{69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}" + ProjectSection(ProjectDependencies) = postProject + {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE} = {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PanelSwCustomActions", "PanelSwCustomActions\PanelSwCustomActions.vcxproj", "{0C3A56AA-8073-44E1-8DE4-C257D581BFF0}" + ProjectSection(ProjectDependencies) = postProject + {7C6B230A-9186-4C1E-B61D-E803CC36A347} = {7C6B230A-9186-4C1E-B61D-E803CC36A347} + {46D02BC4-720A-4B33-AA27-4103E7349F02} = {46D02BC4-720A-4B33-AA27-4103E7349F02} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnitTests", "UnitTests", "{B533D9FC-4927-4A05-892D-B90E8BEDCF5D}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ReadIniValuesUT", "UnitTests\ReadIniValuesUT\ReadIniValuesUT.wixproj", "{EEC5D4C5-9873-42E1-8A7F-79DB5314592B}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "CustomUninstallKeyUT", "UnitTests\CustomUninstallKeyUT\CustomUninstallKeyUT.wixproj", "{5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "RemoveRegistryValueUT", "UnitTests\RemoveRegistryValueUT\RemoveRegistryValueUT.wixproj", "{301175D9-93BD-49D2-8AE2-31693630372C}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "XmlSearchUT", "UnitTests\XmlSearchUT\XmlSearchUT.wixproj", "{0631B7FA-D5A5-4B4B-8289-E0415420D6C7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CaCommon", "CaCommon\CaCommon.vcxproj", "{7C6B230A-9186-4C1E-B61D-E803CC36A347}" + ProjectSection(ProjectDependencies) = postProject + {46D02BC4-720A-4B33-AA27-4103E7349F02} = {46D02BC4-720A-4B33-AA27-4103E7349F02} + EndProjectSection +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "TelemetryUT", "UnitTests\TelemetryUT\TelemetryUT.wixproj", "{12C34100-BC94-48E7-AE28-8B62CAD23155}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "MsiSqlQueryUT", "UnitTests\MsiSqlQueryUT\MsiSqlQueryUT.wixproj", "{9831ED5E-E812-484B-BDCF-AB27ED9297F6}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "RegexUT", "UnitTests\RegexUT\RegexUT.wixproj", "{738E0950-AD2F-49B0-A791-94E7E011E233}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "FileOperationsUT", "UnitTests\FileOperationsUT\FileOperationsUT.wixproj", "{2B87572F-9B38-4F39-A213-97C1AC64703E}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "TaskScheulerUT", "UnitTests\TaskScheulerUT\TaskScheulerUT.wixproj", "{31F20547-2522-4643-AE23-B5B4E25A8852}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{096EB3BA-5DCA-4121-8407-C93F31997339}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + ..\.github\workflows\codeql-analysis.yml = ..\.github\workflows\codeql-analysis.yml + Directory.Build.props = Directory.Build.props + Directory.Packages.props = Directory.Packages.props + dirs.proj = dirs.proj + ..\.github\workflows\github-actions-build.yml = ..\.github\workflows\github-actions-build.yml + global.json = global.json + LICENSE.md = LICENSE.md + nuget.config = nuget.config + Nuget\PanelSwWixExtension4.props = Nuget\PanelSwWixExtension4.props + Nuget\PanelSwWixExtension4.targets = Nuget\PanelSwWixExtension4.targets + ..\.github\workflows\publish-build.yml = ..\.github\workflows\publish-build.yml + README.md = README.md + TidyBuild.custom.props = TidyBuild.custom.props + TidyBuild.custom.targets = TidyBuild.custom.targets + TidyBuild.user.props = TidyBuild.user.props + EndProjectSection +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ExecOnComponentUT", "UnitTests\ExecOnComponentUT\ExecOnComponentUT.wixproj", "{80C0972A-EB37-4DF3-95DB-704EB7F7965C}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "DismUT", "UnitTests\DismUT\DismUT.wixproj", "{E9A9526B-0AD2-4DE2-A154-6558B99A4287}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PswManagedCA", "PswManagedCA\PswManagedCA.csproj", "{EEC82796-3809-4D8B-9F2B-D9F1DB044E39}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ZipFileUT", "UnitTests\ZipFileUT\ZipFileUT.wixproj", "{272D736A-5479-4915-B8FE-5A0D908AB61F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Dism", "Dism\Dism.vcxproj", "{E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ServiceConfigUT", "UnitTests\ServiceConfigUT\ServiceConfigUT.wixproj", "{C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "CleanPendingFileRenameOperationsUT", "UnitTests\CleanPendingFileRenameOperationsUT\CleanPendingFileRenameOperationsUT.wixproj", "{EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "InstallUtilUT", "UnitTests\InstallUtilUT\InstallUtilUT.wixproj", "{7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "SqlSearchUT", "UnitTests\SqlSearchUT\SqlSearchUT.wixproj", "{4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "BackupAndRestoreUT", "UnitTests\BackupAndRestoreUT\BackupAndRestoreUT.wixproj", "{21F86B1E-9F55-4CC8-93C7-BD237157B7F5}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "CreateSelfSignCertificateUT", "UnitTests\CreateSelfSignCertificateUT\CreateSelfSignCertificateUT.wixproj", "{95697A34-1519-42EC-A96B-3090AE6EAE2A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProtoCaLib", "ProtoCaLib\ProtoCaLib.vcxproj", "{46D02BC4-720A-4B33-AA27-4103E7349F02}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SetPropertyFromPipeBAF", "UnitTests\SetPropertyFromPipe\SetPropertyFromPipeBAF\SetPropertyFromPipeBAF.vcxproj", "{EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "SetPropertyFromPipeBootstrapper", "UnitTests\SetPropertyFromPipe\SetPropertyFromPipeBootstrapper\SetPropertyFromPipeBootstrapper.wixproj", "{F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "SetPropertyFromPipeSetup", "UnitTests\SetPropertyFromPipe\SetPropertyFromPipeSetup\SetPropertyFromPipeSetup.wixproj", "{C3F36939-174F-4A7C-880E-B25875B7ABDC}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "EvaluateExpressionUT", "UnitTests\EvaluateExpressionUT\EvaluateExpressionUT.wixproj", "{CBA21767-A300-4048-BCD4-4757F6FD0BEA}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "DiskSpaceUT", "UnitTests\DiskSpaceUT\DiskSpaceUT.wixproj", "{58646CCF-55D2-4131-BCAC-8670D372BA83}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "JsonJPathUT", "UnitTests\JsonJPathUT\JsonJPathUT.wixproj", "{CF761D68-A8DE-41F3-8888-91B0C70B2C8E}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "AccountNamesUT", "UnitTests\AccountNamesUT\AccountNamesUT.wixproj", "{49D91747-0876-4315-AD43-089EAC141670}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "AccountSidSearchUT", "UnitTests\AccountSidSearchUT\AccountSidSearchUT.wixproj", "{9373BDEE-4179-45BD-BA91-467C37729852}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ForceVersionUT", "UnitTests\ForceVersionUT\ForceVersionUT.wixproj", "{F773F85B-CD8B-4FDD-ABFC-B74C018AB900}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "WebsiteConfigUT", "UnitTests\WebsiteConfigUT\WebsiteConfigUT.wixproj", "{742496FF-76A2-419C-BA48-BE8C6C1C23EB}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "VersionCompareUT", "UnitTests\VersionCompareUT\VersionCompareUT.wixproj", "{E386BD7E-2DDC-4F30-8FD0-2ED41E851159}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "PathSearchUT", "UnitTests\PathSearchUT\PathSearchUT.wixproj", "{0FBEE09F-52C0-4AA2-8238-D55067106829}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "CustomActionDataUT", "UnitTests\CustomActionDataUT\CustomActionDataUT.wixproj", "{F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "StringUT", "UnitTests\StringUT\StringUT.wixproj", "{60408F7C-8FEB-4F24-A437-6DE8850223AB}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "WmiSearchUT", "UnitTests\WmiSearchUT\WmiSearchUT.wixproj", "{426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "RestartLocalResourcesUT", "UnitTests\RestartLocalResourcesUT\RestartLocalResourcesUT.wixproj", "{71CA675A-453F-4756-924F-CD36C6C162E8}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "Md5HashUT", "UnitTests\Md5HashUT\Md5HashUT.wixproj", "{42520F9E-9D2A-4FD8-B747-2CC03120F588}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "SplitFileUT", "UnitTests\SplitFileUT\SplitFileUT.wixproj", "{1C727FB4-460C-4EDA-B751-0593E2910B4C}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "PreprocessorUT", "UnitTests\PreprocessorUT\PreprocessorUT.wixproj", "{9D192FCB-1D43-4DA7-902E-8076E757A045}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "PayloadUT", "UnitTests\PayloadUT\PayloadUT.wixproj", "{D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PanelSwWixHarvestExtension", "PanelSwWixHarvestExtension\PanelSwWixHarvestExtension.csproj", "{3463E375-46E1-46DD-9AF4-8E925F581B93}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "PromptFileDowngradesUT", "UnitTests\PromptFileDowngradesUT\PromptFileDowngradesUT.wixproj", "{1C35A94C-5A83-49BB-A855-D052F0B0BFB4}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "HeatExtUT", "UnitTests\HeatExtUT\HeatExtUT.wixproj", "{EBB376C5-D953-405D-BFA5-1E50FD10F419}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DeferredExePackage", "DeferredExePackage\DeferredExePackage.vcxproj", "{B729FB3C-25CF-4216-940D-69EA78779CD7}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "IsWindowsVersionOrGreaterUT", "UnitTests\IsWindowsVersionOrGreaterUT\IsWindowsVersionOrGreaterUT.wixproj", "{E4D1FCE8-9273-47DE-A672-209F010F74B7}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ListProcessorFeaturesUT", "UnitTests\ListProcessorFeaturesUT\ListProcessorFeaturesUT.wixproj", "{DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ExecuteCommandUT", "UnitTests\ExecuteCommandUT\ExecuteCommandUT.wixproj", "{A01CBD4F-7229-4B71-8657-7683C98BCB7C}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "DuplicateFolderUT", "UnitTests\DuplicateFolderUT\DuplicateFolderUT.wixproj", "{5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}" +EndProject +Project("{B7DD6F7E-DEF8-4E67-B5B7-07EF123DB6F0}") = "ContainerTemplateUT", "UnitTests\ContainerTemplateUT\ContainerTemplateUT.wixproj", "{7BB9BAE3-93F4-47AD-A630-E0FE147F3026}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PanelSwBackendExtension", "PanelSwBackendExtension\PanelSwBackendExtension.vcxproj", "{6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Debug|ARM64.ActiveCfg = Debug|x86 + {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Debug|ARM64.Build.0 = Debug|x86 + {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Debug|x64.ActiveCfg = Debug|x64 + {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Debug|x64.Build.0 = Debug|x64 + {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Debug|x86.ActiveCfg = Release|x86 + {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Debug|x86.Build.0 = Release|x86 + {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Release|ARM64.ActiveCfg = Release|x86 + {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Release|ARM64.Build.0 = Release|x86 + {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Release|x64.ActiveCfg = Release|x64 + {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Release|x64.Build.0 = Release|x64 + {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Release|x86.ActiveCfg = Release|x86 + {B6AC15A8-5EF9-4F89-ACCC-3F5C3FC04BCE}.Release|x86.Build.0 = Release|x86 + {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Debug|ARM64.Build.0 = Debug|Any CPU + {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Debug|x64.ActiveCfg = Debug|Any CPU + {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Debug|x64.Build.0 = Debug|Any CPU + {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Debug|x86.ActiveCfg = Debug|Any CPU + {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Debug|x86.Build.0 = Debug|Any CPU + {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Release|ARM64.ActiveCfg = Release|Any CPU + {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Release|ARM64.Build.0 = Release|Any CPU + {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Release|x64.ActiveCfg = Release|Any CPU + {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Release|x64.Build.0 = Release|Any CPU + {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Release|x86.ActiveCfg = Release|Any CPU + {69972F7F-F1CF-44AA-8F76-B4A5A4F1B309}.Release|x86.Build.0 = Release|Any CPU + {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Debug|ARM64.ActiveCfg = Release|Win32 + {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Debug|ARM64.Build.0 = Release|Win32 + {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Debug|x64.ActiveCfg = Release|Win32 + {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Debug|x64.Build.0 = Release|Win32 + {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Debug|x86.ActiveCfg = Release|Win32 + {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Debug|x86.Build.0 = Release|Win32 + {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Release|ARM64.ActiveCfg = Release|ARM64 + {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Release|ARM64.Build.0 = Release|ARM64 + {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Release|x64.ActiveCfg = Release|Win32 + {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Release|x64.Build.0 = Release|Win32 + {0C3A56AA-8073-44E1-8DE4-C257D581BFF0}.Release|x86.ActiveCfg = Release|Win32 + {EEC5D4C5-9873-42E1-8A7F-79DB5314592B}.Debug|ARM64.ActiveCfg = Release|x86 + {EEC5D4C5-9873-42E1-8A7F-79DB5314592B}.Debug|x64.ActiveCfg = Debug|x64 + {EEC5D4C5-9873-42E1-8A7F-79DB5314592B}.Debug|x64.Build.0 = Debug|x64 + {EEC5D4C5-9873-42E1-8A7F-79DB5314592B}.Debug|x86.ActiveCfg = Release|x86 + {EEC5D4C5-9873-42E1-8A7F-79DB5314592B}.Release|ARM64.ActiveCfg = Release|x86 + {EEC5D4C5-9873-42E1-8A7F-79DB5314592B}.Release|x64.ActiveCfg = Release|x64 + {EEC5D4C5-9873-42E1-8A7F-79DB5314592B}.Release|x64.Build.0 = Release|x64 + {EEC5D4C5-9873-42E1-8A7F-79DB5314592B}.Release|x86.ActiveCfg = Release|x86 + {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}.Debug|ARM64.ActiveCfg = Release|x86 + {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}.Debug|x64.ActiveCfg = Debug|x64 + {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}.Debug|x64.Build.0 = Debug|x64 + {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}.Debug|x86.ActiveCfg = Release|x86 + {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}.Release|ARM64.ActiveCfg = Release|x86 + {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}.Release|x64.ActiveCfg = Release|x64 + {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}.Release|x64.Build.0 = Release|x64 + {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F}.Release|x86.ActiveCfg = Release|x86 + {301175D9-93BD-49D2-8AE2-31693630372C}.Debug|ARM64.ActiveCfg = Release|x86 + {301175D9-93BD-49D2-8AE2-31693630372C}.Debug|x64.ActiveCfg = Debug|x64 + {301175D9-93BD-49D2-8AE2-31693630372C}.Debug|x64.Build.0 = Debug|x64 + {301175D9-93BD-49D2-8AE2-31693630372C}.Debug|x86.ActiveCfg = Release|x86 + {301175D9-93BD-49D2-8AE2-31693630372C}.Release|ARM64.ActiveCfg = Release|x86 + {301175D9-93BD-49D2-8AE2-31693630372C}.Release|x64.ActiveCfg = Release|x64 + {301175D9-93BD-49D2-8AE2-31693630372C}.Release|x64.Build.0 = Release|x64 + {301175D9-93BD-49D2-8AE2-31693630372C}.Release|x86.ActiveCfg = Release|x86 + {0631B7FA-D5A5-4B4B-8289-E0415420D6C7}.Debug|ARM64.ActiveCfg = Release|x86 + {0631B7FA-D5A5-4B4B-8289-E0415420D6C7}.Debug|x64.ActiveCfg = Debug|x64 + {0631B7FA-D5A5-4B4B-8289-E0415420D6C7}.Debug|x64.Build.0 = Debug|x64 + {0631B7FA-D5A5-4B4B-8289-E0415420D6C7}.Debug|x86.ActiveCfg = Release|x86 + {0631B7FA-D5A5-4B4B-8289-E0415420D6C7}.Release|ARM64.ActiveCfg = Release|x86 + {0631B7FA-D5A5-4B4B-8289-E0415420D6C7}.Release|x64.ActiveCfg = Release|x64 + {0631B7FA-D5A5-4B4B-8289-E0415420D6C7}.Release|x64.Build.0 = Release|x64 + {0631B7FA-D5A5-4B4B-8289-E0415420D6C7}.Release|x86.ActiveCfg = Release|x86 + {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Debug|ARM64.ActiveCfg = Release|Win32 + {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Debug|x64.ActiveCfg = Release|Win32 + {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Debug|x64.Build.0 = Release|Win32 + {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Debug|x86.ActiveCfg = Release|Win32 + {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Release|ARM64.ActiveCfg = Release|ARM64 + {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Release|ARM64.Build.0 = Release|ARM64 + {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Release|x64.ActiveCfg = Release|Win32 + {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Release|x64.Build.0 = Release|Win32 + {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Release|x86.ActiveCfg = Release|Win32 + {7C6B230A-9186-4C1E-B61D-E803CC36A347}.Release|x86.Build.0 = Release|Win32 + {12C34100-BC94-48E7-AE28-8B62CAD23155}.Debug|ARM64.ActiveCfg = Release|x86 + {12C34100-BC94-48E7-AE28-8B62CAD23155}.Debug|x64.ActiveCfg = Debug|x64 + {12C34100-BC94-48E7-AE28-8B62CAD23155}.Debug|x64.Build.0 = Debug|x64 + {12C34100-BC94-48E7-AE28-8B62CAD23155}.Debug|x86.ActiveCfg = Release|x86 + {12C34100-BC94-48E7-AE28-8B62CAD23155}.Release|ARM64.ActiveCfg = Release|x86 + {12C34100-BC94-48E7-AE28-8B62CAD23155}.Release|x64.ActiveCfg = Release|x64 + {12C34100-BC94-48E7-AE28-8B62CAD23155}.Release|x64.Build.0 = Release|x64 + {12C34100-BC94-48E7-AE28-8B62CAD23155}.Release|x86.ActiveCfg = Release|x86 + {9831ED5E-E812-484B-BDCF-AB27ED9297F6}.Debug|ARM64.ActiveCfg = Release|x86 + {9831ED5E-E812-484B-BDCF-AB27ED9297F6}.Debug|x64.ActiveCfg = Debug|x64 + {9831ED5E-E812-484B-BDCF-AB27ED9297F6}.Debug|x64.Build.0 = Debug|x64 + {9831ED5E-E812-484B-BDCF-AB27ED9297F6}.Debug|x86.ActiveCfg = Release|x86 + {9831ED5E-E812-484B-BDCF-AB27ED9297F6}.Release|ARM64.ActiveCfg = Release|x86 + {9831ED5E-E812-484B-BDCF-AB27ED9297F6}.Release|x64.ActiveCfg = Release|x64 + {9831ED5E-E812-484B-BDCF-AB27ED9297F6}.Release|x64.Build.0 = Release|x64 + {9831ED5E-E812-484B-BDCF-AB27ED9297F6}.Release|x86.ActiveCfg = Release|x86 + {738E0950-AD2F-49B0-A791-94E7E011E233}.Debug|ARM64.ActiveCfg = Release|x86 + {738E0950-AD2F-49B0-A791-94E7E011E233}.Debug|x64.ActiveCfg = Debug|x64 + {738E0950-AD2F-49B0-A791-94E7E011E233}.Debug|x64.Build.0 = Debug|x64 + {738E0950-AD2F-49B0-A791-94E7E011E233}.Debug|x86.ActiveCfg = Release|x86 + {738E0950-AD2F-49B0-A791-94E7E011E233}.Release|ARM64.ActiveCfg = Release|x86 + {738E0950-AD2F-49B0-A791-94E7E011E233}.Release|x64.ActiveCfg = Release|x64 + {738E0950-AD2F-49B0-A791-94E7E011E233}.Release|x64.Build.0 = Release|x64 + {738E0950-AD2F-49B0-A791-94E7E011E233}.Release|x86.ActiveCfg = Release|x86 + {2B87572F-9B38-4F39-A213-97C1AC64703E}.Debug|ARM64.ActiveCfg = Release|x86 + {2B87572F-9B38-4F39-A213-97C1AC64703E}.Debug|x64.ActiveCfg = Debug|x64 + {2B87572F-9B38-4F39-A213-97C1AC64703E}.Debug|x64.Build.0 = Debug|x64 + {2B87572F-9B38-4F39-A213-97C1AC64703E}.Debug|x86.ActiveCfg = Release|x86 + {2B87572F-9B38-4F39-A213-97C1AC64703E}.Release|ARM64.ActiveCfg = Release|x86 + {2B87572F-9B38-4F39-A213-97C1AC64703E}.Release|x64.ActiveCfg = Release|x64 + {2B87572F-9B38-4F39-A213-97C1AC64703E}.Release|x64.Build.0 = Release|x64 + {2B87572F-9B38-4F39-A213-97C1AC64703E}.Release|x86.ActiveCfg = Release|x86 + {31F20547-2522-4643-AE23-B5B4E25A8852}.Debug|ARM64.ActiveCfg = Release|x86 + {31F20547-2522-4643-AE23-B5B4E25A8852}.Debug|x64.ActiveCfg = Debug|x64 + {31F20547-2522-4643-AE23-B5B4E25A8852}.Debug|x64.Build.0 = Debug|x64 + {31F20547-2522-4643-AE23-B5B4E25A8852}.Debug|x86.ActiveCfg = Release|x86 + {31F20547-2522-4643-AE23-B5B4E25A8852}.Release|ARM64.ActiveCfg = Release|x86 + {31F20547-2522-4643-AE23-B5B4E25A8852}.Release|x64.ActiveCfg = Release|x64 + {31F20547-2522-4643-AE23-B5B4E25A8852}.Release|x64.Build.0 = Release|x64 + {31F20547-2522-4643-AE23-B5B4E25A8852}.Release|x86.ActiveCfg = Release|x86 + {80C0972A-EB37-4DF3-95DB-704EB7F7965C}.Debug|ARM64.ActiveCfg = Release|x86 + {80C0972A-EB37-4DF3-95DB-704EB7F7965C}.Debug|x64.ActiveCfg = Debug|x64 + {80C0972A-EB37-4DF3-95DB-704EB7F7965C}.Debug|x64.Build.0 = Debug|x64 + {80C0972A-EB37-4DF3-95DB-704EB7F7965C}.Debug|x86.ActiveCfg = Release|x86 + {80C0972A-EB37-4DF3-95DB-704EB7F7965C}.Release|ARM64.ActiveCfg = Release|x86 + {80C0972A-EB37-4DF3-95DB-704EB7F7965C}.Release|x64.ActiveCfg = Release|x64 + {80C0972A-EB37-4DF3-95DB-704EB7F7965C}.Release|x64.Build.0 = Release|x64 + {80C0972A-EB37-4DF3-95DB-704EB7F7965C}.Release|x86.ActiveCfg = Release|x86 + {E9A9526B-0AD2-4DE2-A154-6558B99A4287}.Debug|ARM64.ActiveCfg = Release|x86 + {E9A9526B-0AD2-4DE2-A154-6558B99A4287}.Debug|x64.ActiveCfg = Debug|x64 + {E9A9526B-0AD2-4DE2-A154-6558B99A4287}.Debug|x64.Build.0 = Debug|x64 + {E9A9526B-0AD2-4DE2-A154-6558B99A4287}.Debug|x86.ActiveCfg = Release|x86 + {E9A9526B-0AD2-4DE2-A154-6558B99A4287}.Release|ARM64.ActiveCfg = Release|x86 + {E9A9526B-0AD2-4DE2-A154-6558B99A4287}.Release|x64.ActiveCfg = Release|x64 + {E9A9526B-0AD2-4DE2-A154-6558B99A4287}.Release|x64.Build.0 = Release|x64 + {E9A9526B-0AD2-4DE2-A154-6558B99A4287}.Release|x86.ActiveCfg = Release|x86 + {EEC82796-3809-4D8B-9F2B-D9F1DB044E39}.Debug|ARM64.ActiveCfg = Release|x86 + {EEC82796-3809-4D8B-9F2B-D9F1DB044E39}.Debug|x64.ActiveCfg = Debug|x64 + {EEC82796-3809-4D8B-9F2B-D9F1DB044E39}.Debug|x64.Build.0 = Debug|x64 + {EEC82796-3809-4D8B-9F2B-D9F1DB044E39}.Debug|x86.ActiveCfg = Release|x86 + {EEC82796-3809-4D8B-9F2B-D9F1DB044E39}.Release|ARM64.ActiveCfg = Release|x86 + {EEC82796-3809-4D8B-9F2B-D9F1DB044E39}.Release|x64.ActiveCfg = Release|x64 + {EEC82796-3809-4D8B-9F2B-D9F1DB044E39}.Release|x64.Build.0 = Release|x64 + {EEC82796-3809-4D8B-9F2B-D9F1DB044E39}.Release|x86.ActiveCfg = Release|x86 + {272D736A-5479-4915-B8FE-5A0D908AB61F}.Debug|ARM64.ActiveCfg = Release|x86 + {272D736A-5479-4915-B8FE-5A0D908AB61F}.Debug|x64.ActiveCfg = Debug|x64 + {272D736A-5479-4915-B8FE-5A0D908AB61F}.Debug|x64.Build.0 = Debug|x64 + {272D736A-5479-4915-B8FE-5A0D908AB61F}.Debug|x86.ActiveCfg = Release|x86 + {272D736A-5479-4915-B8FE-5A0D908AB61F}.Release|ARM64.ActiveCfg = Release|x86 + {272D736A-5479-4915-B8FE-5A0D908AB61F}.Release|x64.ActiveCfg = Release|x64 + {272D736A-5479-4915-B8FE-5A0D908AB61F}.Release|x64.Build.0 = Release|x64 + {272D736A-5479-4915-B8FE-5A0D908AB61F}.Release|x86.ActiveCfg = Release|x86 + {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Debug|ARM64.ActiveCfg = Release|Win32 + {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Debug|ARM64.Build.0 = Release|Win32 + {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Debug|x64.ActiveCfg = Release|x64 + {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Debug|x64.Build.0 = Release|x64 + {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Debug|x86.ActiveCfg = Release|Win32 + {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Debug|x86.Build.0 = Release|Win32 + {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Release|ARM64.ActiveCfg = Release|Win32 + {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Release|x64.ActiveCfg = Release|x64 + {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Release|x64.Build.0 = Release|x64 + {E08BD5F2-B8DE-4EEE-A77F-FD82678664AC}.Release|x86.ActiveCfg = Release|Win32 + {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}.Debug|ARM64.ActiveCfg = Release|x86 + {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}.Debug|x64.ActiveCfg = Debug|x64 + {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}.Debug|x64.Build.0 = Debug|x64 + {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}.Debug|x86.ActiveCfg = Release|x86 + {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}.Release|ARM64.ActiveCfg = Release|x86 + {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}.Release|x64.ActiveCfg = Release|x64 + {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}.Release|x64.Build.0 = Release|x64 + {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896}.Release|x86.ActiveCfg = Release|x86 + {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}.Debug|ARM64.ActiveCfg = Release|x86 + {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}.Debug|x64.ActiveCfg = Debug|x64 + {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}.Debug|x64.Build.0 = Debug|x64 + {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}.Debug|x86.ActiveCfg = Release|x86 + {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}.Release|ARM64.ActiveCfg = Release|x86 + {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}.Release|x64.ActiveCfg = Release|x64 + {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}.Release|x64.Build.0 = Release|x64 + {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05}.Release|x86.ActiveCfg = Release|x86 + {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}.Debug|ARM64.ActiveCfg = Release|x86 + {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}.Debug|x64.ActiveCfg = Debug|x64 + {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}.Debug|x64.Build.0 = Debug|x64 + {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}.Debug|x86.ActiveCfg = Release|x86 + {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}.Release|ARM64.ActiveCfg = Release|x86 + {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}.Release|x64.ActiveCfg = Release|x64 + {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}.Release|x64.Build.0 = Release|x64 + {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460}.Release|x86.ActiveCfg = Release|x86 + {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}.Debug|ARM64.ActiveCfg = Release|x86 + {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}.Debug|x64.ActiveCfg = Debug|x64 + {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}.Debug|x64.Build.0 = Debug|x64 + {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}.Debug|x86.ActiveCfg = Release|x86 + {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}.Release|ARM64.ActiveCfg = Release|x86 + {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}.Release|x64.ActiveCfg = Release|x64 + {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}.Release|x64.Build.0 = Release|x64 + {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF}.Release|x86.ActiveCfg = Release|x86 + {21F86B1E-9F55-4CC8-93C7-BD237157B7F5}.Debug|ARM64.ActiveCfg = Release|x86 + {21F86B1E-9F55-4CC8-93C7-BD237157B7F5}.Debug|x64.ActiveCfg = Debug|x64 + {21F86B1E-9F55-4CC8-93C7-BD237157B7F5}.Debug|x64.Build.0 = Debug|x64 + {21F86B1E-9F55-4CC8-93C7-BD237157B7F5}.Debug|x86.ActiveCfg = Release|x86 + {21F86B1E-9F55-4CC8-93C7-BD237157B7F5}.Release|ARM64.ActiveCfg = Release|x86 + {21F86B1E-9F55-4CC8-93C7-BD237157B7F5}.Release|x64.ActiveCfg = Release|x64 + {21F86B1E-9F55-4CC8-93C7-BD237157B7F5}.Release|x64.Build.0 = Release|x64 + {21F86B1E-9F55-4CC8-93C7-BD237157B7F5}.Release|x86.ActiveCfg = Release|x86 + {95697A34-1519-42EC-A96B-3090AE6EAE2A}.Debug|ARM64.ActiveCfg = Release|x86 + {95697A34-1519-42EC-A96B-3090AE6EAE2A}.Debug|x64.ActiveCfg = Debug|x64 + {95697A34-1519-42EC-A96B-3090AE6EAE2A}.Debug|x64.Build.0 = Debug|x64 + {95697A34-1519-42EC-A96B-3090AE6EAE2A}.Debug|x86.ActiveCfg = Release|x86 + {95697A34-1519-42EC-A96B-3090AE6EAE2A}.Release|ARM64.ActiveCfg = Release|x86 + {95697A34-1519-42EC-A96B-3090AE6EAE2A}.Release|x64.ActiveCfg = Release|x64 + {95697A34-1519-42EC-A96B-3090AE6EAE2A}.Release|x64.Build.0 = Release|x64 + {95697A34-1519-42EC-A96B-3090AE6EAE2A}.Release|x86.ActiveCfg = Release|x86 + {46D02BC4-720A-4B33-AA27-4103E7349F02}.Debug|ARM64.ActiveCfg = Release|Win32 + {46D02BC4-720A-4B33-AA27-4103E7349F02}.Debug|x64.ActiveCfg = Release|Win32 + {46D02BC4-720A-4B33-AA27-4103E7349F02}.Debug|x64.Build.0 = Release|Win32 + {46D02BC4-720A-4B33-AA27-4103E7349F02}.Debug|x86.ActiveCfg = Release|Win32 + {46D02BC4-720A-4B33-AA27-4103E7349F02}.Release|ARM64.ActiveCfg = Release|ARM64 + {46D02BC4-720A-4B33-AA27-4103E7349F02}.Release|ARM64.Build.0 = Release|ARM64 + {46D02BC4-720A-4B33-AA27-4103E7349F02}.Release|x64.ActiveCfg = Release|Win32 + {46D02BC4-720A-4B33-AA27-4103E7349F02}.Release|x64.Build.0 = Release|Win32 + {46D02BC4-720A-4B33-AA27-4103E7349F02}.Release|x86.ActiveCfg = Release|Win32 + {46D02BC4-720A-4B33-AA27-4103E7349F02}.Release|x86.Build.0 = Release|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Debug|ARM64.ActiveCfg = Release|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Debug|x64.ActiveCfg = Release|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Debug|x64.Build.0 = Release|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Debug|x86.ActiveCfg = Release|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Release|ARM64.ActiveCfg = Release|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Release|x64.ActiveCfg = Release|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Release|x64.Build.0 = Release|Win32 + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02}.Release|x86.ActiveCfg = Release|Win32 + {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}.Debug|ARM64.ActiveCfg = Release|x86 + {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}.Debug|x64.ActiveCfg = Debug|x64 + {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}.Debug|x64.Build.0 = Debug|x64 + {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}.Debug|x86.ActiveCfg = Release|x86 + {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}.Release|ARM64.ActiveCfg = Release|x86 + {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}.Release|x64.ActiveCfg = Release|x64 + {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}.Release|x64.Build.0 = Release|x64 + {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7}.Release|x86.ActiveCfg = Release|x86 + {C3F36939-174F-4A7C-880E-B25875B7ABDC}.Debug|ARM64.ActiveCfg = Release|x86 + {C3F36939-174F-4A7C-880E-B25875B7ABDC}.Debug|x64.ActiveCfg = Debug|x64 + {C3F36939-174F-4A7C-880E-B25875B7ABDC}.Debug|x64.Build.0 = Debug|x64 + {C3F36939-174F-4A7C-880E-B25875B7ABDC}.Debug|x86.ActiveCfg = Release|x86 + {C3F36939-174F-4A7C-880E-B25875B7ABDC}.Release|ARM64.ActiveCfg = Release|x86 + {C3F36939-174F-4A7C-880E-B25875B7ABDC}.Release|x64.ActiveCfg = Release|x64 + {C3F36939-174F-4A7C-880E-B25875B7ABDC}.Release|x64.Build.0 = Release|x64 + {C3F36939-174F-4A7C-880E-B25875B7ABDC}.Release|x86.ActiveCfg = Release|x86 + {CBA21767-A300-4048-BCD4-4757F6FD0BEA}.Debug|ARM64.ActiveCfg = Release|x86 + {CBA21767-A300-4048-BCD4-4757F6FD0BEA}.Debug|x64.ActiveCfg = Debug|x64 + {CBA21767-A300-4048-BCD4-4757F6FD0BEA}.Debug|x64.Build.0 = Debug|x64 + {CBA21767-A300-4048-BCD4-4757F6FD0BEA}.Debug|x86.ActiveCfg = Release|x86 + {CBA21767-A300-4048-BCD4-4757F6FD0BEA}.Release|ARM64.ActiveCfg = Release|x86 + {CBA21767-A300-4048-BCD4-4757F6FD0BEA}.Release|x64.ActiveCfg = Release|x64 + {CBA21767-A300-4048-BCD4-4757F6FD0BEA}.Release|x64.Build.0 = Release|x64 + {CBA21767-A300-4048-BCD4-4757F6FD0BEA}.Release|x86.ActiveCfg = Release|x86 + {58646CCF-55D2-4131-BCAC-8670D372BA83}.Debug|ARM64.ActiveCfg = Release|x86 + {58646CCF-55D2-4131-BCAC-8670D372BA83}.Debug|x64.ActiveCfg = Debug|x64 + {58646CCF-55D2-4131-BCAC-8670D372BA83}.Debug|x64.Build.0 = Debug|x64 + {58646CCF-55D2-4131-BCAC-8670D372BA83}.Debug|x86.ActiveCfg = Release|x86 + {58646CCF-55D2-4131-BCAC-8670D372BA83}.Release|ARM64.ActiveCfg = Release|x86 + {58646CCF-55D2-4131-BCAC-8670D372BA83}.Release|x64.ActiveCfg = Release|x64 + {58646CCF-55D2-4131-BCAC-8670D372BA83}.Release|x64.Build.0 = Release|x64 + {58646CCF-55D2-4131-BCAC-8670D372BA83}.Release|x86.ActiveCfg = Release|x86 + {CF761D68-A8DE-41F3-8888-91B0C70B2C8E}.Debug|ARM64.ActiveCfg = Release|x86 + {CF761D68-A8DE-41F3-8888-91B0C70B2C8E}.Debug|x64.ActiveCfg = Debug|x64 + {CF761D68-A8DE-41F3-8888-91B0C70B2C8E}.Debug|x64.Build.0 = Debug|x64 + {CF761D68-A8DE-41F3-8888-91B0C70B2C8E}.Debug|x86.ActiveCfg = Release|x86 + {CF761D68-A8DE-41F3-8888-91B0C70B2C8E}.Release|ARM64.ActiveCfg = Release|x86 + {CF761D68-A8DE-41F3-8888-91B0C70B2C8E}.Release|x64.ActiveCfg = Release|x64 + {CF761D68-A8DE-41F3-8888-91B0C70B2C8E}.Release|x64.Build.0 = Release|x64 + {CF761D68-A8DE-41F3-8888-91B0C70B2C8E}.Release|x86.ActiveCfg = Release|x86 + {49D91747-0876-4315-AD43-089EAC141670}.Debug|ARM64.ActiveCfg = Release|x86 + {49D91747-0876-4315-AD43-089EAC141670}.Debug|x64.ActiveCfg = Debug|x64 + {49D91747-0876-4315-AD43-089EAC141670}.Debug|x64.Build.0 = Debug|x64 + {49D91747-0876-4315-AD43-089EAC141670}.Debug|x86.ActiveCfg = Release|x86 + {49D91747-0876-4315-AD43-089EAC141670}.Release|ARM64.ActiveCfg = Release|x86 + {49D91747-0876-4315-AD43-089EAC141670}.Release|x64.ActiveCfg = Release|x64 + {49D91747-0876-4315-AD43-089EAC141670}.Release|x64.Build.0 = Release|x64 + {49D91747-0876-4315-AD43-089EAC141670}.Release|x86.ActiveCfg = Release|x86 + {9373BDEE-4179-45BD-BA91-467C37729852}.Debug|ARM64.ActiveCfg = Release|x86 + {9373BDEE-4179-45BD-BA91-467C37729852}.Debug|x64.ActiveCfg = Debug|x64 + {9373BDEE-4179-45BD-BA91-467C37729852}.Debug|x64.Build.0 = Debug|x64 + {9373BDEE-4179-45BD-BA91-467C37729852}.Debug|x86.ActiveCfg = Release|x86 + {9373BDEE-4179-45BD-BA91-467C37729852}.Release|ARM64.ActiveCfg = Release|x86 + {9373BDEE-4179-45BD-BA91-467C37729852}.Release|x64.ActiveCfg = Release|x64 + {9373BDEE-4179-45BD-BA91-467C37729852}.Release|x64.Build.0 = Release|x64 + {9373BDEE-4179-45BD-BA91-467C37729852}.Release|x86.ActiveCfg = Release|x86 + {F773F85B-CD8B-4FDD-ABFC-B74C018AB900}.Debug|ARM64.ActiveCfg = Release|x86 + {F773F85B-CD8B-4FDD-ABFC-B74C018AB900}.Debug|x64.ActiveCfg = Debug|x64 + {F773F85B-CD8B-4FDD-ABFC-B74C018AB900}.Debug|x64.Build.0 = Debug|x64 + {F773F85B-CD8B-4FDD-ABFC-B74C018AB900}.Debug|x86.ActiveCfg = Release|x86 + {F773F85B-CD8B-4FDD-ABFC-B74C018AB900}.Release|ARM64.ActiveCfg = Release|x86 + {F773F85B-CD8B-4FDD-ABFC-B74C018AB900}.Release|x64.ActiveCfg = Release|x64 + {F773F85B-CD8B-4FDD-ABFC-B74C018AB900}.Release|x64.Build.0 = Release|x64 + {F773F85B-CD8B-4FDD-ABFC-B74C018AB900}.Release|x86.ActiveCfg = Release|x86 + {742496FF-76A2-419C-BA48-BE8C6C1C23EB}.Debug|ARM64.ActiveCfg = Release|x86 + {742496FF-76A2-419C-BA48-BE8C6C1C23EB}.Debug|x64.ActiveCfg = Debug|x64 + {742496FF-76A2-419C-BA48-BE8C6C1C23EB}.Debug|x64.Build.0 = Debug|x64 + {742496FF-76A2-419C-BA48-BE8C6C1C23EB}.Debug|x86.ActiveCfg = Release|x86 + {742496FF-76A2-419C-BA48-BE8C6C1C23EB}.Release|ARM64.ActiveCfg = Release|x86 + {742496FF-76A2-419C-BA48-BE8C6C1C23EB}.Release|x64.ActiveCfg = Release|x64 + {742496FF-76A2-419C-BA48-BE8C6C1C23EB}.Release|x64.Build.0 = Release|x64 + {742496FF-76A2-419C-BA48-BE8C6C1C23EB}.Release|x86.ActiveCfg = Release|x86 + {E386BD7E-2DDC-4F30-8FD0-2ED41E851159}.Debug|ARM64.ActiveCfg = Release|x86 + {E386BD7E-2DDC-4F30-8FD0-2ED41E851159}.Debug|x64.ActiveCfg = Debug|x64 + {E386BD7E-2DDC-4F30-8FD0-2ED41E851159}.Debug|x64.Build.0 = Debug|x64 + {E386BD7E-2DDC-4F30-8FD0-2ED41E851159}.Debug|x86.ActiveCfg = Release|x86 + {E386BD7E-2DDC-4F30-8FD0-2ED41E851159}.Release|ARM64.ActiveCfg = Release|x86 + {E386BD7E-2DDC-4F30-8FD0-2ED41E851159}.Release|x64.ActiveCfg = Release|x64 + {E386BD7E-2DDC-4F30-8FD0-2ED41E851159}.Release|x64.Build.0 = Release|x64 + {E386BD7E-2DDC-4F30-8FD0-2ED41E851159}.Release|x86.ActiveCfg = Release|x86 + {0FBEE09F-52C0-4AA2-8238-D55067106829}.Debug|ARM64.ActiveCfg = Release|x86 + {0FBEE09F-52C0-4AA2-8238-D55067106829}.Debug|x64.ActiveCfg = Debug|x64 + {0FBEE09F-52C0-4AA2-8238-D55067106829}.Debug|x64.Build.0 = Debug|x64 + {0FBEE09F-52C0-4AA2-8238-D55067106829}.Debug|x86.ActiveCfg = Release|x86 + {0FBEE09F-52C0-4AA2-8238-D55067106829}.Release|ARM64.ActiveCfg = Release|x86 + {0FBEE09F-52C0-4AA2-8238-D55067106829}.Release|x64.ActiveCfg = Release|x64 + {0FBEE09F-52C0-4AA2-8238-D55067106829}.Release|x64.Build.0 = Release|x64 + {0FBEE09F-52C0-4AA2-8238-D55067106829}.Release|x86.ActiveCfg = Release|x86 + {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}.Debug|ARM64.ActiveCfg = Release|x86 + {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}.Debug|x64.ActiveCfg = Debug|x64 + {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}.Debug|x64.Build.0 = Debug|x64 + {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}.Debug|x86.ActiveCfg = Release|x86 + {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}.Release|ARM64.ActiveCfg = Release|x86 + {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}.Release|x64.ActiveCfg = Release|x64 + {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}.Release|x64.Build.0 = Release|x64 + {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621}.Release|x86.ActiveCfg = Release|x86 + {60408F7C-8FEB-4F24-A437-6DE8850223AB}.Debug|ARM64.ActiveCfg = Release|x86 + {60408F7C-8FEB-4F24-A437-6DE8850223AB}.Debug|x64.ActiveCfg = Debug|x64 + {60408F7C-8FEB-4F24-A437-6DE8850223AB}.Debug|x64.Build.0 = Debug|x64 + {60408F7C-8FEB-4F24-A437-6DE8850223AB}.Debug|x86.ActiveCfg = Release|x86 + {60408F7C-8FEB-4F24-A437-6DE8850223AB}.Release|ARM64.ActiveCfg = Release|x86 + {60408F7C-8FEB-4F24-A437-6DE8850223AB}.Release|x64.ActiveCfg = Release|x64 + {60408F7C-8FEB-4F24-A437-6DE8850223AB}.Release|x64.Build.0 = Release|x64 + {60408F7C-8FEB-4F24-A437-6DE8850223AB}.Release|x86.ActiveCfg = Release|x86 + {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}.Debug|ARM64.ActiveCfg = Release|x86 + {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}.Debug|x64.ActiveCfg = Debug|x64 + {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}.Debug|x64.Build.0 = Debug|x64 + {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}.Debug|x86.ActiveCfg = Release|x86 + {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}.Release|ARM64.ActiveCfg = Release|x86 + {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}.Release|x64.ActiveCfg = Release|x64 + {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}.Release|x64.Build.0 = Release|x64 + {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A}.Release|x86.ActiveCfg = Release|x86 + {71CA675A-453F-4756-924F-CD36C6C162E8}.Debug|ARM64.ActiveCfg = Release|x86 + {71CA675A-453F-4756-924F-CD36C6C162E8}.Debug|x64.ActiveCfg = Debug|x64 + {71CA675A-453F-4756-924F-CD36C6C162E8}.Debug|x64.Build.0 = Debug|x64 + {71CA675A-453F-4756-924F-CD36C6C162E8}.Debug|x86.ActiveCfg = Release|x86 + {71CA675A-453F-4756-924F-CD36C6C162E8}.Release|ARM64.ActiveCfg = Release|x86 + {71CA675A-453F-4756-924F-CD36C6C162E8}.Release|x64.ActiveCfg = Release|x64 + {71CA675A-453F-4756-924F-CD36C6C162E8}.Release|x64.Build.0 = Release|x64 + {71CA675A-453F-4756-924F-CD36C6C162E8}.Release|x86.ActiveCfg = Release|x86 + {42520F9E-9D2A-4FD8-B747-2CC03120F588}.Debug|ARM64.ActiveCfg = Release|x86 + {42520F9E-9D2A-4FD8-B747-2CC03120F588}.Debug|x64.ActiveCfg = Debug|x64 + {42520F9E-9D2A-4FD8-B747-2CC03120F588}.Debug|x64.Build.0 = Debug|x64 + {42520F9E-9D2A-4FD8-B747-2CC03120F588}.Debug|x86.ActiveCfg = Release|x86 + {42520F9E-9D2A-4FD8-B747-2CC03120F588}.Release|ARM64.ActiveCfg = Release|x86 + {42520F9E-9D2A-4FD8-B747-2CC03120F588}.Release|x64.ActiveCfg = Release|x64 + {42520F9E-9D2A-4FD8-B747-2CC03120F588}.Release|x64.Build.0 = Release|x64 + {42520F9E-9D2A-4FD8-B747-2CC03120F588}.Release|x86.ActiveCfg = Release|x86 + {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Debug|ARM64.ActiveCfg = Debug|x86 + {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Debug|ARM64.Build.0 = Debug|x86 + {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Debug|x64.ActiveCfg = Debug|x64 + {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Debug|x64.Build.0 = Debug|x64 + {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Debug|x86.ActiveCfg = Debug|x86 + {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Debug|x86.Build.0 = Debug|x86 + {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Release|ARM64.ActiveCfg = Release|x86 + {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Release|x64.ActiveCfg = Release|x64 + {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Release|x64.Build.0 = Release|x64 + {1C727FB4-460C-4EDA-B751-0593E2910B4C}.Release|x86.ActiveCfg = Release|x86 + {9D192FCB-1D43-4DA7-902E-8076E757A045}.Debug|ARM64.ActiveCfg = Debug|x86 + {9D192FCB-1D43-4DA7-902E-8076E757A045}.Debug|ARM64.Build.0 = Debug|x86 + {9D192FCB-1D43-4DA7-902E-8076E757A045}.Debug|x64.ActiveCfg = Debug|x64 + {9D192FCB-1D43-4DA7-902E-8076E757A045}.Debug|x64.Build.0 = Debug|x64 + {9D192FCB-1D43-4DA7-902E-8076E757A045}.Debug|x86.ActiveCfg = Debug|x86 + {9D192FCB-1D43-4DA7-902E-8076E757A045}.Debug|x86.Build.0 = Debug|x86 + {9D192FCB-1D43-4DA7-902E-8076E757A045}.Release|ARM64.ActiveCfg = Release|x86 + {9D192FCB-1D43-4DA7-902E-8076E757A045}.Release|x64.ActiveCfg = Release|x64 + {9D192FCB-1D43-4DA7-902E-8076E757A045}.Release|x64.Build.0 = Release|x64 + {9D192FCB-1D43-4DA7-902E-8076E757A045}.Release|x86.ActiveCfg = Release|x86 + {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Debug|ARM64.ActiveCfg = Debug|x86 + {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Debug|ARM64.Build.0 = Debug|x86 + {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Debug|x64.ActiveCfg = Debug|x64 + {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Debug|x64.Build.0 = Debug|x64 + {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Debug|x86.ActiveCfg = Debug|x86 + {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Debug|x86.Build.0 = Debug|x86 + {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Release|ARM64.ActiveCfg = Release|x86 + {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Release|x64.ActiveCfg = Release|x64 + {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Release|x64.Build.0 = Release|x64 + {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49}.Release|x86.ActiveCfg = Release|x86 + {3463E375-46E1-46DD-9AF4-8E925F581B93}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {3463E375-46E1-46DD-9AF4-8E925F581B93}.Debug|ARM64.Build.0 = Debug|Any CPU + {3463E375-46E1-46DD-9AF4-8E925F581B93}.Debug|x64.ActiveCfg = Debug|Any CPU + {3463E375-46E1-46DD-9AF4-8E925F581B93}.Debug|x64.Build.0 = Debug|Any CPU + {3463E375-46E1-46DD-9AF4-8E925F581B93}.Debug|x86.ActiveCfg = Debug|Any CPU + {3463E375-46E1-46DD-9AF4-8E925F581B93}.Debug|x86.Build.0 = Debug|Any CPU + {3463E375-46E1-46DD-9AF4-8E925F581B93}.Release|ARM64.ActiveCfg = Release|Any CPU + {3463E375-46E1-46DD-9AF4-8E925F581B93}.Release|ARM64.Build.0 = Release|Any CPU + {3463E375-46E1-46DD-9AF4-8E925F581B93}.Release|x64.ActiveCfg = Release|Any CPU + {3463E375-46E1-46DD-9AF4-8E925F581B93}.Release|x64.Build.0 = Release|Any CPU + {3463E375-46E1-46DD-9AF4-8E925F581B93}.Release|x86.ActiveCfg = Release|Any CPU + {3463E375-46E1-46DD-9AF4-8E925F581B93}.Release|x86.Build.0 = Release|Any CPU + {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Debug|ARM64.Build.0 = Debug|ARM64 + {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Debug|x64.ActiveCfg = Debug|x64 + {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Debug|x64.Build.0 = Debug|x64 + {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Debug|x86.ActiveCfg = Debug|x86 + {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Debug|x86.Build.0 = Debug|x86 + {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Release|ARM64.ActiveCfg = Release|ARM64 + {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Release|ARM64.Build.0 = Release|ARM64 + {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Release|x64.ActiveCfg = Release|x64 + {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Release|x64.Build.0 = Release|x64 + {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Release|x86.ActiveCfg = Release|x86 + {1C35A94C-5A83-49BB-A855-D052F0B0BFB4}.Release|x86.Build.0 = Release|x86 + {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Debug|ARM64.Build.0 = Debug|ARM64 + {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Debug|x64.ActiveCfg = Debug|x64 + {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Debug|x64.Build.0 = Debug|x64 + {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Debug|x86.ActiveCfg = Debug|x86 + {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Debug|x86.Build.0 = Debug|x86 + {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Release|ARM64.ActiveCfg = Release|ARM64 + {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Release|ARM64.Build.0 = Release|ARM64 + {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Release|x64.ActiveCfg = Release|x64 + {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Release|x64.Build.0 = Release|x64 + {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Release|x86.ActiveCfg = Release|x86 + {EBB376C5-D953-405D-BFA5-1E50FD10F419}.Release|x86.Build.0 = Release|x86 + {B729FB3C-25CF-4216-940D-69EA78779CD7}.Debug|ARM64.ActiveCfg = Release|ARM64 + {B729FB3C-25CF-4216-940D-69EA78779CD7}.Debug|ARM64.Build.0 = Release|ARM64 + {B729FB3C-25CF-4216-940D-69EA78779CD7}.Debug|x64.ActiveCfg = Release|x64 + {B729FB3C-25CF-4216-940D-69EA78779CD7}.Debug|x64.Build.0 = Release|x64 + {B729FB3C-25CF-4216-940D-69EA78779CD7}.Debug|x86.ActiveCfg = Release|Win32 + {B729FB3C-25CF-4216-940D-69EA78779CD7}.Debug|x86.Build.0 = Release|Win32 + {B729FB3C-25CF-4216-940D-69EA78779CD7}.Release|ARM64.ActiveCfg = Release|ARM64 + {B729FB3C-25CF-4216-940D-69EA78779CD7}.Release|ARM64.Build.0 = Release|ARM64 + {B729FB3C-25CF-4216-940D-69EA78779CD7}.Release|x64.ActiveCfg = Release|x64 + {B729FB3C-25CF-4216-940D-69EA78779CD7}.Release|x64.Build.0 = Release|x64 + {B729FB3C-25CF-4216-940D-69EA78779CD7}.Release|x86.ActiveCfg = Release|Win32 + {B729FB3C-25CF-4216-940D-69EA78779CD7}.Release|x86.Build.0 = Release|Win32 + {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Debug|ARM64.Build.0 = Debug|ARM64 + {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Debug|x64.ActiveCfg = Debug|x64 + {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Debug|x64.Build.0 = Debug|x64 + {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Debug|x86.ActiveCfg = Debug|x86 + {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Debug|x86.Build.0 = Debug|x86 + {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Release|ARM64.ActiveCfg = Release|ARM64 + {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Release|ARM64.Build.0 = Release|ARM64 + {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Release|x64.ActiveCfg = Release|x64 + {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Release|x64.Build.0 = Release|x64 + {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Release|x86.ActiveCfg = Release|x86 + {E4D1FCE8-9273-47DE-A672-209F010F74B7}.Release|x86.Build.0 = Release|x86 + {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Debug|ARM64.ActiveCfg = Debug|x86 + {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Debug|ARM64.Build.0 = Debug|x86 + {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Debug|x64.ActiveCfg = Debug|x86 + {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Debug|x64.Build.0 = Debug|x86 + {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Debug|x86.ActiveCfg = Debug|x86 + {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Debug|x86.Build.0 = Debug|x86 + {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Release|ARM64.ActiveCfg = Release|x86 + {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Release|ARM64.Build.0 = Release|x86 + {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Release|x64.ActiveCfg = Release|x86 + {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Release|x64.Build.0 = Release|x86 + {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Release|x86.ActiveCfg = Release|x86 + {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A}.Release|x86.Build.0 = Release|x86 + {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Debug|ARM64.Build.0 = Debug|ARM64 + {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Debug|x64.ActiveCfg = Debug|x64 + {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Debug|x64.Build.0 = Debug|x64 + {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Debug|x86.ActiveCfg = Debug|x86 + {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Debug|x86.Build.0 = Debug|x86 + {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Release|ARM64.ActiveCfg = Release|ARM64 + {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Release|ARM64.Build.0 = Release|ARM64 + {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Release|x64.ActiveCfg = Release|x64 + {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Release|x64.Build.0 = Release|x64 + {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Release|x86.ActiveCfg = Release|x86 + {A01CBD4F-7229-4B71-8657-7683C98BCB7C}.Release|x86.Build.0 = Release|x86 + {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Debug|ARM64.Build.0 = Debug|ARM64 + {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Debug|x64.ActiveCfg = Debug|x64 + {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Debug|x64.Build.0 = Debug|x64 + {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Debug|x86.ActiveCfg = Debug|x86 + {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Debug|x86.Build.0 = Debug|x86 + {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Release|ARM64.ActiveCfg = Release|ARM64 + {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Release|ARM64.Build.0 = Release|ARM64 + {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Release|x64.ActiveCfg = Release|x64 + {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Release|x64.Build.0 = Release|x64 + {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Release|x86.ActiveCfg = Release|x86 + {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD}.Release|x86.Build.0 = Release|x86 + {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Debug|ARM64.Build.0 = Debug|ARM64 + {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Debug|x64.ActiveCfg = Debug|x64 + {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Debug|x64.Build.0 = Debug|x64 + {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Debug|x86.ActiveCfg = Debug|x86 + {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Debug|x86.Build.0 = Debug|x86 + {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Release|ARM64.ActiveCfg = Release|ARM64 + {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Release|ARM64.Build.0 = Release|ARM64 + {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Release|x64.ActiveCfg = Release|x64 + {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Release|x64.Build.0 = Release|x64 + {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Release|x86.ActiveCfg = Release|x86 + {7BB9BAE3-93F4-47AD-A630-E0FE147F3026}.Release|x86.Build.0 = Release|x86 + {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Debug|ARM64.ActiveCfg = Release|Win32 + {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Debug|ARM64.Build.0 = Release|Win32 + {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Debug|x64.ActiveCfg = Release|Win32 + {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Debug|x64.Build.0 = Release|Win32 + {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Debug|x86.ActiveCfg = Release|Win32 + {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Debug|x86.Build.0 = Release|Win32 + {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Release|ARM64.ActiveCfg = Release|Win32 + {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Release|ARM64.Build.0 = Release|Win32 + {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Release|x64.ActiveCfg = Release|Win32 + {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Release|x64.Build.0 = Release|Win32 + {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Release|x86.ActiveCfg = Release|Win32 + {6CE73DA5-F91B-4CFD-96B5-7FED3241B39F}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {EEC5D4C5-9873-42E1-8A7F-79DB5314592B} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {5E7E80C3-8093-4DF6-AD3D-DE3F2872B01F} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {301175D9-93BD-49D2-8AE2-31693630372C} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {0631B7FA-D5A5-4B4B-8289-E0415420D6C7} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {12C34100-BC94-48E7-AE28-8B62CAD23155} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {9831ED5E-E812-484B-BDCF-AB27ED9297F6} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {738E0950-AD2F-49B0-A791-94E7E011E233} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {2B87572F-9B38-4F39-A213-97C1AC64703E} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {31F20547-2522-4643-AE23-B5B4E25A8852} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {80C0972A-EB37-4DF3-95DB-704EB7F7965C} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {E9A9526B-0AD2-4DE2-A154-6558B99A4287} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {272D736A-5479-4915-B8FE-5A0D908AB61F} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {C6FC6CB8-13AD-48BE-8FB1-8A7BC5790896} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {EA03A92C-1984-4F2A-9D4F-4EA2C451AE05} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {7F31BB12-8494-4A6E-A2B8-ECF9FE25B460} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {4B0E8514-6BEE-41A5-AD4B-DF5F3BFEEFEF} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {21F86B1E-9F55-4CC8-93C7-BD237157B7F5} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {95697A34-1519-42EC-A96B-3090AE6EAE2A} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {EB0A7D51-2133-4EE7-B6CA-87DBEAC67E02} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {F37B5C48-DD17-4FF6-AF58-1BD697C2C1D7} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {C3F36939-174F-4A7C-880E-B25875B7ABDC} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {CBA21767-A300-4048-BCD4-4757F6FD0BEA} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {58646CCF-55D2-4131-BCAC-8670D372BA83} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {CF761D68-A8DE-41F3-8888-91B0C70B2C8E} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {49D91747-0876-4315-AD43-089EAC141670} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {9373BDEE-4179-45BD-BA91-467C37729852} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {F773F85B-CD8B-4FDD-ABFC-B74C018AB900} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {742496FF-76A2-419C-BA48-BE8C6C1C23EB} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {E386BD7E-2DDC-4F30-8FD0-2ED41E851159} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {0FBEE09F-52C0-4AA2-8238-D55067106829} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {F0FAAEE2-E1C5-4122-80FA-CE8CA58F7621} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {60408F7C-8FEB-4F24-A437-6DE8850223AB} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {426A6EC1-D3D6-4A88-85B9-4595A04E6D4A} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {71CA675A-453F-4756-924F-CD36C6C162E8} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {42520F9E-9D2A-4FD8-B747-2CC03120F588} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {1C727FB4-460C-4EDA-B751-0593E2910B4C} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {9D192FCB-1D43-4DA7-902E-8076E757A045} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {D3F4B72D-4C8D-4CED-91B6-33AB2A926A49} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {1C35A94C-5A83-49BB-A855-D052F0B0BFB4} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {EBB376C5-D953-405D-BFA5-1E50FD10F419} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {E4D1FCE8-9273-47DE-A672-209F010F74B7} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {DE2A15B5-B20E-47C3-87FB-7881D4D7E15A} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {A01CBD4F-7229-4B71-8657-7683C98BCB7C} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {5B7782E9-9913-4E25-81F4-D98DB5E8B4BD} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + {7BB9BAE3-93F4-47AD-A630-E0FE147F3026} = {B533D9FC-4927-4A05-892D-B90E8BEDCF5D} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F5B6389D-77ED-4938-A322-8DFCA4D9FEF5} + EndGlobalSection +EndGlobal diff --git a/PanelSwWixExtension/MessageResources.Designer.cs b/src/PanelSwWixExtension/MessageResources.Designer.cs similarity index 92% rename from PanelSwWixExtension/MessageResources.Designer.cs rename to src/PanelSwWixExtension/MessageResources.Designer.cs index 3dce76aa..db9d8e3b 100644 --- a/PanelSwWixExtension/MessageResources.Designer.cs +++ b/src/PanelSwWixExtension/MessageResources.Designer.cs @@ -78,6 +78,15 @@ internal static string ExecuteCommandSequence { } } + /// + /// Looks up a localized string similar to Could not find ContainerTemplate element to create container '{0}' with.. + /// + internal static string MissingContainerTemplate { + get { + return ResourceManager.GetString("MissingContainerTemplate", resourceCulture); + } + } + /// /// Looks up a localized string similar to Payload '{0}' is larger than the maximal size set in ContainerTemplate, {1}. /// diff --git a/PanelSwWixExtension/MessageResources.resx b/src/PanelSwWixExtension/MessageResources.resx similarity index 97% rename from PanelSwWixExtension/MessageResources.resx rename to src/PanelSwWixExtension/MessageResources.resx index 36d16b04..a8855e9d 100644 --- a/PanelSwWixExtension/MessageResources.resx +++ b/src/PanelSwWixExtension/MessageResources.resx @@ -123,6 +123,9 @@ The InstallExecuteSequence table contains action '{1}' in between actions required for ExecuteCommand action '{0}'. Please schedule commands to execute after '{0}' or before 'Prepare{0}' + + Could not find ContainerTemplate element to create container '{0}' with. + Payload '{0}' is larger than the maximal size set in ContainerTemplate, {1} diff --git a/PanelSwWixExtension/PanelSwBurnBackendBinder.cs b/src/PanelSwWixExtension/PanelSwBurnBackendBinder.cs similarity index 90% rename from PanelSwWixExtension/PanelSwBurnBackendBinder.cs rename to src/PanelSwWixExtension/PanelSwBurnBackendBinder.cs index 7dcd0910..a1ac669b 100644 --- a/PanelSwWixExtension/PanelSwBurnBackendBinder.cs +++ b/src/PanelSwWixExtension/PanelSwBurnBackendBinder.cs @@ -22,6 +22,7 @@ protected override IReadOnlyCollection SymbolDefin _intermediateSymbols = new List { PSW_ContainerTemplate.SymbolDefinition, + PSW_ContainerExtensionData.SymbolDefinition, }; } return _intermediateSymbols; @@ -30,7 +31,7 @@ protected override IReadOnlyCollection SymbolDefin public override bool TryProcessSymbol(IntermediateSection section, IntermediateSymbol symbol) { - if (symbol is PSW_ContainerTemplate) + if (symbol is PSW_ContainerTemplate || symbol is PSW_ContainerExtensionData) { return true; } @@ -119,9 +120,14 @@ private void FinalizeAutoContainers(IntermediateSection section) defaultContainer.Name = string.Format(containerTemplate.CabinetTemplate, 0); defaultContainer.Type = containerTemplate.DefaultType; #if EnableZipContainer - if (containerTemplate.Compression == PSW_ContainerTemplate.ContainerCompressionType.Zip) + if (containerTemplate.Compression != PSW_ContainerTemplate.ContainerCompressionType.Cab) { defaultContainer.BundleExtensionRef = PanelSwWixExtension.CONTAINER_EXTENSION_ID; + BackendHelper.AddBundleExtensionData(PanelSwWixExtension.CONTAINER_EXTENSION_ID, new PSW_ContainerExtensionData(defaultContainer.SourceLineNumbers) + { + Compression = containerTemplate.Compression, + ContainerId = defaultContainer.Id.Id + }); } #endif @@ -160,7 +166,16 @@ private void FinalizeAutoContainers(IntermediateSection section) container.Type = containerTemplate.DefaultType; #if EnableZipContainer container.BundleExtensionRef = defaultContainer.BundleExtensionRef; + if (containerTemplate.Compression != PSW_ContainerTemplate.ContainerCompressionType.Cab) + { + BackendHelper.AddBundleExtensionData(PanelSwWixExtension.CONTAINER_EXTENSION_ID, new PSW_ContainerExtensionData(container.SourceLineNumbers) + { + Compression = containerTemplate.Compression, + ContainerId = container.Id.Id + }); + } #endif + containerSize[container] = 0; if (payload.FileSize.HasValue && (payload.FileSize.Value > containerTemplate.MaximumUncompressedContainerSize)) diff --git a/src/PanelSwWixExtension/PanelSwBurnContainer.cs b/src/PanelSwWixExtension/PanelSwBurnContainer.cs new file mode 100644 index 00000000..8214b9ac --- /dev/null +++ b/src/PanelSwWixExtension/PanelSwBurnContainer.cs @@ -0,0 +1,131 @@ +using PanelSw.Wix.Extensions.Symbols; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Xml; +using WixToolset.Data; +using WixToolset.Data.Burn; +using WixToolset.Data.Symbols; +using WixToolset.Extensibility; + +namespace PanelSw.Wix.Extensions +{ + public class PanelSwBurnContainer : BaseBurnContainerExtension + { + public override IReadOnlyCollection ContainerExtensionIds => new[] { PanelSwWixExtension.CONTAINER_EXTENSION_ID }; + + public override void CreateContainer(WixBundleContainerSymbol container, IEnumerable containerPayloads, out string sha512, out long size) + { + sha512 = null; + size = 0; + PSW_ContainerTemplate containerTemplate = null; + foreach (IntermediateSection section in Context.IntermediateRepresentation.Sections) + { + containerTemplate = section.Symbols.FirstOrDefault(s => s is PSW_ContainerTemplate) as PSW_ContainerTemplate; + if (containerTemplate != null) + { + break; + } + } + if (containerTemplate == null) + { + Messaging.Write(PanelSwWixErrorMessages.MissingContainerTemplate(container.SourceLineNumbers, container.Id.Id)); + return; + } + + try + { + if (File.Exists(container.WorkingPath)) + { + File.Delete(container.WorkingPath); + } + + switch (containerTemplate.Compression) + { + case PSW_ContainerTemplate.ContainerCompressionType.Zip: + CreateContainerZip(container, containerPayloads); + break; + case PSW_ContainerTemplate.ContainerCompressionType.SevenZip: + CreateContainerLzma(container, containerPayloads); + break; + } + CalculateHashAndSize(container.WorkingPath, out sha512, out size); + } + catch (Exception ex) + { + Messaging.Write(PanelSwWixErrorMessages.ContainerError(container.SourceLineNumbers, container.Id.Id, ex.Message)); + return; + } + } + + private void CreateContainerZip(WixBundleContainerSymbol container, IEnumerable containerPayloads) + { + using (ZipArchive zipFile = ZipFile.Open(container.WorkingPath, ZipArchiveMode.Create)) + { + foreach (WixBundlePayloadSymbol payload in containerPayloads) + { + string entryName = payload.EmbeddedId; + FileInfo fileInfo = new FileInfo(payload.SourceFile.Path); + + ZipArchiveEntry entry = zipFile.CreateEntry(entryName); + entry.LastWriteTime = fileInfo.LastWriteTime; + using (Stream ws = entry.Open()) + { + using (FileStream rs = File.Open(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) + { + rs.CopyTo(ws); + } + } + } + } + } + + private void CreateContainerLzma(WixBundleContainerSymbol container, IEnumerable containerPayloads) + { + List entries = new List(containerPayloads.Select( + p => new SevenZap.SevenZap.FileEntry() + { + EntryName = p.EmbeddedId, + FullPath = Path.GetFullPath(p.SourceFile.Path) + })); + SevenZap.SevenZap.UpdateArchive(container.WorkingPath, entries); + } + + public override void ExtractContainer(string containerPath, string outputFolder, string containerId, XmlElement extensionDataNode) + { + XmlNamespaceManager nmspc = new XmlNamespaceManager(extensionDataNode.OwnerDocument.NameTable); + nmspc.AddNamespace("ext", BurnConstants.BundleExtensionDataNamespace); + + XmlNode compressionAttr = extensionDataNode.SelectSingleNode($"//ext:PSW_ContainerExtensionData[@ContainerId='{containerId}']/@Compression", nmspc); + if ((compressionAttr == null) || !Enum.TryParse(compressionAttr.Value, out PSW_ContainerTemplate.ContainerCompressionType compression)) + { + throw new ArgumentException("Can't extract container since manifest does not contain required extension data"); + } + + switch (compression) + { + case PSW_ContainerTemplate.ContainerCompressionType.Zip: + ExtractContainerZip(containerPath, outputFolder); + break; + case PSW_ContainerTemplate.ContainerCompressionType.SevenZip: + ExtractContainerLzma(containerPath, outputFolder); + break; + default: + throw new ArgumentException($"Can't extract container with {compression} compression"); + } + } + + private void ExtractContainerZip(string containerPath, string outputFolder) + { + ZipFile.ExtractToDirectory(containerPath, outputFolder); + } + + private void ExtractContainerLzma(string containerPath, string outputFolder) + { + SevenZap.SevenZap.Extract(containerPath, outputFolder); + } + } +} diff --git a/PanelSwWixExtension/PanelSwWiBackendBinder.cs b/src/PanelSwWixExtension/PanelSwWiBackendBinder.cs similarity index 100% rename from PanelSwWixExtension/PanelSwWiBackendBinder.cs rename to src/PanelSwWixExtension/PanelSwWiBackendBinder.cs diff --git a/PanelSwWixExtension/PanelSwWixCompiler.cs b/src/PanelSwWixExtension/PanelSwWixCompiler.cs similarity index 99% rename from PanelSwWixExtension/PanelSwWixCompiler.cs rename to src/PanelSwWixExtension/PanelSwWixCompiler.cs index 7a8e0cde..45f3960a 100644 --- a/PanelSwWixExtension/PanelSwWixCompiler.cs +++ b/src/PanelSwWixExtension/PanelSwWixCompiler.cs @@ -379,7 +379,8 @@ private void ParseContainerTemplateElement(IntermediateSection section, XElement if (string.IsNullOrEmpty(cabinetTemplate)) { - cabinetTemplate = "bundle-attached-{0}." + compression.ToString().ToLower(); + string ext = (compression == PSW_ContainerTemplate.ContainerCompressionType.SevenZip) ? "7z" : compression.ToString().ToLower(); + cabinetTemplate = "bundle-attached-{0}." + ext; } if (!cabinetTemplate.Contains("{0}")) { @@ -403,7 +404,7 @@ private void ParseContainerTemplateElement(IntermediateSection section, XElement symbol.MaximumUncompressedExeSize = maximumUncompressedExeSize; symbol.Compression = compression; - if (compression == PSW_ContainerTemplate.ContainerCompressionType.Zip) + if (compression != PSW_ContainerTemplate.ContainerCompressionType.Cab) { ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.WixBundleExtension, "PanelSwWixContainer"); } diff --git a/PanelSwWixExtension/PanelSwWixExtData.cs b/src/PanelSwWixExtension/PanelSwWixExtData.cs similarity index 98% rename from PanelSwWixExtension/PanelSwWixExtData.cs rename to src/PanelSwWixExtension/PanelSwWixExtData.cs index ad61b4c7..0feee8e8 100644 --- a/PanelSwWixExtension/PanelSwWixExtData.cs +++ b/src/PanelSwWixExtension/PanelSwWixExtData.cs @@ -31,6 +31,9 @@ public override bool TryGetSymbolDefinitionByName(string name, out IntermediateS case nameof(PSW_ConcatFiles): symbolDefinition = PSW_ConcatFiles.SymbolDefinition; break; + case nameof(PSW_ContainerExtensionData): + symbolDefinition = PSW_ContainerExtensionData.SymbolDefinition; + break; case nameof(PSW_ContainerTemplate): symbolDefinition = PSW_ContainerTemplate.SymbolDefinition; break; diff --git a/PanelSwWixExtension/PanelSwWixExtension.cs b/src/PanelSwWixExtension/PanelSwWixExtension.cs similarity index 100% rename from PanelSwWixExtension/PanelSwWixExtension.cs rename to src/PanelSwWixExtension/PanelSwWixExtension.cs diff --git a/PanelSwWixExtension/PanelSwWixExtension.csproj b/src/PanelSwWixExtension/PanelSwWixExtension.csproj similarity index 68% rename from PanelSwWixExtension/PanelSwWixExtension.csproj rename to src/PanelSwWixExtension/PanelSwWixExtension.csproj index 9ea69235..33106207 100644 --- a/PanelSwWixExtension/PanelSwWixExtension.csproj +++ b/src/PanelSwWixExtension/PanelSwWixExtension.csproj @@ -14,10 +14,6 @@ False - - - - true true @@ -28,7 +24,7 @@ true Nir Bar Panel::Software Ltd. - ..\nuget-out + ..\..\nuget-out LICENSE.md README.md WiX MSI Installer WixToolset CustomAction @@ -44,11 +40,11 @@ - - + + - + @@ -58,10 +54,28 @@ - - + + + + + + + + + + + + + + Copy7Zap;$(PackDependsOn) + + + + + + @@ -94,3 +108,4 @@ + \ No newline at end of file diff --git a/PanelSwWixExtension/PanelSwWixExtensionMessage.cs b/src/PanelSwWixExtension/PanelSwWixExtensionMessage.cs similarity index 73% rename from PanelSwWixExtension/PanelSwWixExtensionMessage.cs rename to src/PanelSwWixExtension/PanelSwWixExtensionMessage.cs index c0e42f45..2d08776a 100644 --- a/PanelSwWixExtension/PanelSwWixExtensionMessage.cs +++ b/src/PanelSwWixExtension/PanelSwWixExtensionMessage.cs @@ -14,12 +14,16 @@ public static Message PayloadExceedsSize(SourceLineNumber sourceLineNumber, stri } public static Message ContainerError(SourceLineNumber sourceLineNumber, string containerId, string error) { - return new Message(sourceLineNumber, MessageLevel.Warning, (int)PswErrorId.ContainerError, MessageResources.ContainerError, containerId, error); + return new Message(sourceLineNumber, MessageLevel.Error, (int)PswErrorId.ContainerError, MessageResources.ContainerError, containerId, error); } public static Message PswWixAttribute(SourceLineNumber sourceLineNumber, string attribute, string element) { return new Message(sourceLineNumber, MessageLevel.Error, (int)PswErrorId.PswWixAttribute, MessageResources.PswWixAttribute, attribute, element); } + public static Message MissingContainerTemplate(SourceLineNumber sourceLineNumber, string containerId) + { + return new Message(sourceLineNumber, MessageLevel.Error, (int)PswErrorId.MissingContainerTemplate, MessageResources.MissingContainerTemplate, containerId); + } } public enum PswErrorId : int @@ -28,5 +32,6 @@ public enum PswErrorId : int PayloadExceedsSize, ContainerError, PswWixAttribute, + MissingContainerTemplate, } } diff --git a/PanelSwWixExtension/PanelSwWixPreprocessor.cs b/src/PanelSwWixExtension/PanelSwWixPreprocessor.cs similarity index 100% rename from PanelSwWixExtension/PanelSwWixPreprocessor.cs rename to src/PanelSwWixExtension/PanelSwWixPreprocessor.cs diff --git a/PanelSwWixExtension/Symbols/BaseSymbol.cs b/src/PanelSwWixExtension/Symbols/BaseSymbol.cs similarity index 100% rename from PanelSwWixExtension/Symbols/BaseSymbol.cs rename to src/PanelSwWixExtension/Symbols/BaseSymbol.cs diff --git a/PanelSwWixExtension/Symbols/PSW_AccountSidSearch.cs b/src/PanelSwWixExtension/Symbols/PSW_AccountSidSearch.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_AccountSidSearch.cs rename to src/PanelSwWixExtension/Symbols/PSW_AccountSidSearch.cs diff --git a/PanelSwWixExtension/Symbols/PSW_BackupAndRestore.cs b/src/PanelSwWixExtension/Symbols/PSW_BackupAndRestore.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_BackupAndRestore.cs rename to src/PanelSwWixExtension/Symbols/PSW_BackupAndRestore.cs diff --git a/PanelSwWixExtension/Symbols/PSW_CertificateHashSearch.cs b/src/PanelSwWixExtension/Symbols/PSW_CertificateHashSearch.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_CertificateHashSearch.cs rename to src/PanelSwWixExtension/Symbols/PSW_CertificateHashSearch.cs diff --git a/PanelSwWixExtension/Symbols/PSW_ConcatFiles.cs b/src/PanelSwWixExtension/Symbols/PSW_ConcatFiles.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_ConcatFiles.cs rename to src/PanelSwWixExtension/Symbols/PSW_ConcatFiles.cs diff --git a/src/PanelSwWixExtension/Symbols/PSW_ContainerExtensionData.cs b/src/PanelSwWixExtension/Symbols/PSW_ContainerExtensionData.cs new file mode 100644 index 00000000..332b7cb1 --- /dev/null +++ b/src/PanelSwWixExtension/Symbols/PSW_ContainerExtensionData.cs @@ -0,0 +1,43 @@ +using System; +using WixToolset.Data; + +namespace PanelSw.Wix.Extensions.Symbols +{ + internal class PSW_ContainerExtensionData : BaseSymbol + { + public static IntermediateSymbolDefinition SymbolDefinition + { + get + { + return new IntermediateSymbolDefinition(nameof(PSW_ContainerExtensionData), + new IntermediateFieldDefinition[] + { + new IntermediateFieldDefinition(nameof(ContainerId), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(Compression), IntermediateFieldType.String), + } + , typeof(PSW_ContainerExtensionData)); + } + } + + public PSW_ContainerExtensionData(SourceLineNumber sourceLineNumber) + : base(SymbolDefinition, sourceLineNumber, new Identifier(AccessModifier.Global, 0)) + { + } + + public string ContainerId + { + get => (string)this.Fields[0].AsString(); + set => this.Set(0, value); + } + + public PSW_ContainerTemplate.ContainerCompressionType Compression + { + get + { + string v = this.Fields[1].AsString(); + return !string.IsNullOrEmpty(v) && Enum.TryParse(v, out PSW_ContainerTemplate.ContainerCompressionType type) ? type : PSW_ContainerTemplate.ContainerCompressionType.Cab; + } + set => this.Set(1, value.ToString()); + } + } +} diff --git a/PanelSwWixExtension/Symbols/PSW_ContainerTemplate.cs b/src/PanelSwWixExtension/Symbols/PSW_ContainerTemplate.cs similarity index 99% rename from PanelSwWixExtension/Symbols/PSW_ContainerTemplate.cs rename to src/PanelSwWixExtension/Symbols/PSW_ContainerTemplate.cs index 8692ccc9..097da11b 100644 --- a/PanelSwWixExtension/Symbols/PSW_ContainerTemplate.cs +++ b/src/PanelSwWixExtension/Symbols/PSW_ContainerTemplate.cs @@ -10,6 +10,7 @@ public enum ContainerCompressionType { Zip, Cab, + SevenZip, } public static IntermediateSymbolDefinition SymbolDefinition diff --git a/PanelSwWixExtension/Symbols/PSW_CustomUninstallKey.cs b/src/PanelSwWixExtension/Symbols/PSW_CustomUninstallKey.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_CustomUninstallKey.cs rename to src/PanelSwWixExtension/Symbols/PSW_CustomUninstallKey.cs diff --git a/PanelSwWixExtension/Symbols/PSW_DeletePath.cs b/src/PanelSwWixExtension/Symbols/PSW_DeletePath.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_DeletePath.cs rename to src/PanelSwWixExtension/Symbols/PSW_DeletePath.cs diff --git a/PanelSwWixExtension/Symbols/PSW_DiskSpace.cs b/src/PanelSwWixExtension/Symbols/PSW_DiskSpace.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_DiskSpace.cs rename to src/PanelSwWixExtension/Symbols/PSW_DiskSpace.cs diff --git a/PanelSwWixExtension/Symbols/PSW_Dism.cs b/src/PanelSwWixExtension/Symbols/PSW_Dism.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_Dism.cs rename to src/PanelSwWixExtension/Symbols/PSW_Dism.cs diff --git a/PanelSwWixExtension/Symbols/PSW_DuplicateFolder.cs b/src/PanelSwWixExtension/Symbols/PSW_DuplicateFolder.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_DuplicateFolder.cs rename to src/PanelSwWixExtension/Symbols/PSW_DuplicateFolder.cs diff --git a/PanelSwWixExtension/Symbols/PSW_EvaluateExpression.cs b/src/PanelSwWixExtension/Symbols/PSW_EvaluateExpression.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_EvaluateExpression.cs rename to src/PanelSwWixExtension/Symbols/PSW_EvaluateExpression.cs diff --git a/PanelSwWixExtension/Symbols/PSW_ExecOnComponent.cs b/src/PanelSwWixExtension/Symbols/PSW_ExecOnComponent.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_ExecOnComponent.cs rename to src/PanelSwWixExtension/Symbols/PSW_ExecOnComponent.cs diff --git a/PanelSwWixExtension/Symbols/PSW_ExecOnComponent_Environment.cs b/src/PanelSwWixExtension/Symbols/PSW_ExecOnComponent_Environment.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_ExecOnComponent_Environment.cs rename to src/PanelSwWixExtension/Symbols/PSW_ExecOnComponent_Environment.cs diff --git a/PanelSwWixExtension/Symbols/PSW_ExecOnComponent_ExitCode.cs b/src/PanelSwWixExtension/Symbols/PSW_ExecOnComponent_ExitCode.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_ExecOnComponent_ExitCode.cs rename to src/PanelSwWixExtension/Symbols/PSW_ExecOnComponent_ExitCode.cs diff --git a/PanelSwWixExtension/Symbols/PSW_ExecOn_ConsoleOutput.cs b/src/PanelSwWixExtension/Symbols/PSW_ExecOn_ConsoleOutput.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_ExecOn_ConsoleOutput.cs rename to src/PanelSwWixExtension/Symbols/PSW_ExecOn_ConsoleOutput.cs diff --git a/PanelSwWixExtension/Symbols/PSW_ExecuteCommand.cs b/src/PanelSwWixExtension/Symbols/PSW_ExecuteCommand.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_ExecuteCommand.cs rename to src/PanelSwWixExtension/Symbols/PSW_ExecuteCommand.cs diff --git a/PanelSwWixExtension/Symbols/PSW_FileRegex.cs b/src/PanelSwWixExtension/Symbols/PSW_FileRegex.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_FileRegex.cs rename to src/PanelSwWixExtension/Symbols/PSW_FileRegex.cs diff --git a/PanelSwWixExtension/Symbols/PSW_ForceVersion.cs b/src/PanelSwWixExtension/Symbols/PSW_ForceVersion.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_ForceVersion.cs rename to src/PanelSwWixExtension/Symbols/PSW_ForceVersion.cs diff --git a/PanelSwWixExtension/Symbols/PSW_InstallUtil.cs b/src/PanelSwWixExtension/Symbols/PSW_InstallUtil.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_InstallUtil.cs rename to src/PanelSwWixExtension/Symbols/PSW_InstallUtil.cs diff --git a/PanelSwWixExtension/Symbols/PSW_InstallUtil_Arg.cs b/src/PanelSwWixExtension/Symbols/PSW_InstallUtil_Arg.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_InstallUtil_Arg.cs rename to src/PanelSwWixExtension/Symbols/PSW_InstallUtil_Arg.cs diff --git a/PanelSwWixExtension/Symbols/PSW_IsWindowsVersionOrGreater.cs b/src/PanelSwWixExtension/Symbols/PSW_IsWindowsVersionOrGreater.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_IsWindowsVersionOrGreater.cs rename to src/PanelSwWixExtension/Symbols/PSW_IsWindowsVersionOrGreater.cs diff --git a/PanelSwWixExtension/Symbols/PSW_JsonJPath.cs b/src/PanelSwWixExtension/Symbols/PSW_JsonJPath.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_JsonJPath.cs rename to src/PanelSwWixExtension/Symbols/PSW_JsonJPath.cs diff --git a/PanelSwWixExtension/Symbols/PSW_JsonJpathSearch.cs b/src/PanelSwWixExtension/Symbols/PSW_JsonJpathSearch.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_JsonJpathSearch.cs rename to src/PanelSwWixExtension/Symbols/PSW_JsonJpathSearch.cs diff --git a/PanelSwWixExtension/Symbols/PSW_Md5Hash.cs b/src/PanelSwWixExtension/Symbols/PSW_Md5Hash.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_Md5Hash.cs rename to src/PanelSwWixExtension/Symbols/PSW_Md5Hash.cs diff --git a/PanelSwWixExtension/Symbols/PSW_MsiSqlQuery.cs b/src/PanelSwWixExtension/Symbols/PSW_MsiSqlQuery.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_MsiSqlQuery.cs rename to src/PanelSwWixExtension/Symbols/PSW_MsiSqlQuery.cs diff --git a/PanelSwWixExtension/Symbols/PSW_PathSearch.cs b/src/PanelSwWixExtension/Symbols/PSW_PathSearch.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_PathSearch.cs rename to src/PanelSwWixExtension/Symbols/PSW_PathSearch.cs diff --git a/PanelSwWixExtension/Symbols/PSW_Payload.cs b/src/PanelSwWixExtension/Symbols/PSW_Payload.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_Payload.cs rename to src/PanelSwWixExtension/Symbols/PSW_Payload.cs diff --git a/PanelSwWixExtension/Symbols/PSW_ReadIniValues.cs b/src/PanelSwWixExtension/Symbols/PSW_ReadIniValues.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_ReadIniValues.cs rename to src/PanelSwWixExtension/Symbols/PSW_ReadIniValues.cs diff --git a/PanelSwWixExtension/Symbols/PSW_RegularExpression.cs b/src/PanelSwWixExtension/Symbols/PSW_RegularExpression.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_RegularExpression.cs rename to src/PanelSwWixExtension/Symbols/PSW_RegularExpression.cs diff --git a/PanelSwWixExtension/Symbols/PSW_RemoveRegistryValue.cs b/src/PanelSwWixExtension/Symbols/PSW_RemoveRegistryValue.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_RemoveRegistryValue.cs rename to src/PanelSwWixExtension/Symbols/PSW_RemoveRegistryValue.cs diff --git a/PanelSwWixExtension/Symbols/PSW_RestartLocalResources.cs b/src/PanelSwWixExtension/Symbols/PSW_RestartLocalResources.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_RestartLocalResources.cs rename to src/PanelSwWixExtension/Symbols/PSW_RestartLocalResources.cs diff --git a/PanelSwWixExtension/Symbols/PSW_SelfSignCertificate.cs b/src/PanelSwWixExtension/Symbols/PSW_SelfSignCertificate.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_SelfSignCertificate.cs rename to src/PanelSwWixExtension/Symbols/PSW_SelfSignCertificate.cs diff --git a/PanelSwWixExtension/Symbols/PSW_ServiceConfig.cs b/src/PanelSwWixExtension/Symbols/PSW_ServiceConfig.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_ServiceConfig.cs rename to src/PanelSwWixExtension/Symbols/PSW_ServiceConfig.cs diff --git a/PanelSwWixExtension/Symbols/PSW_ServiceConfig_Dependency.cs b/src/PanelSwWixExtension/Symbols/PSW_ServiceConfig_Dependency.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_ServiceConfig_Dependency.cs rename to src/PanelSwWixExtension/Symbols/PSW_ServiceConfig_Dependency.cs diff --git a/PanelSwWixExtension/Symbols/PSW_SetPropertyFromPipe.cs b/src/PanelSwWixExtension/Symbols/PSW_SetPropertyFromPipe.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_SetPropertyFromPipe.cs rename to src/PanelSwWixExtension/Symbols/PSW_SetPropertyFromPipe.cs diff --git a/PanelSwWixExtension/Symbols/PSW_ShellExecute.cs b/src/PanelSwWixExtension/Symbols/PSW_ShellExecute.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_ShellExecute.cs rename to src/PanelSwWixExtension/Symbols/PSW_ShellExecute.cs diff --git a/PanelSwWixExtension/Symbols/PSW_SqlScript.cs b/src/PanelSwWixExtension/Symbols/PSW_SqlScript.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_SqlScript.cs rename to src/PanelSwWixExtension/Symbols/PSW_SqlScript.cs diff --git a/PanelSwWixExtension/Symbols/PSW_SqlScript_Replacements.cs b/src/PanelSwWixExtension/Symbols/PSW_SqlScript_Replacements.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_SqlScript_Replacements.cs rename to src/PanelSwWixExtension/Symbols/PSW_SqlScript_Replacements.cs diff --git a/PanelSwWixExtension/Symbols/PSW_SqlSearch.cs b/src/PanelSwWixExtension/Symbols/PSW_SqlSearch.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_SqlSearch.cs rename to src/PanelSwWixExtension/Symbols/PSW_SqlSearch.cs diff --git a/PanelSwWixExtension/Symbols/PSW_TaskScheduler.cs b/src/PanelSwWixExtension/Symbols/PSW_TaskScheduler.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_TaskScheduler.cs rename to src/PanelSwWixExtension/Symbols/PSW_TaskScheduler.cs diff --git a/PanelSwWixExtension/Symbols/PSW_Telemetry.cs b/src/PanelSwWixExtension/Symbols/PSW_Telemetry.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_Telemetry.cs rename to src/PanelSwWixExtension/Symbols/PSW_Telemetry.cs diff --git a/PanelSwWixExtension/Symbols/PSW_ToLowerCase.cs b/src/PanelSwWixExtension/Symbols/PSW_ToLowerCase.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_ToLowerCase.cs rename to src/PanelSwWixExtension/Symbols/PSW_ToLowerCase.cs diff --git a/PanelSwWixExtension/Symbols/PSW_TopShelf.cs b/src/PanelSwWixExtension/Symbols/PSW_TopShelf.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_TopShelf.cs rename to src/PanelSwWixExtension/Symbols/PSW_TopShelf.cs diff --git a/PanelSwWixExtension/Symbols/PSW_Unzip.cs b/src/PanelSwWixExtension/Symbols/PSW_Unzip.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_Unzip.cs rename to src/PanelSwWixExtension/Symbols/PSW_Unzip.cs diff --git a/PanelSwWixExtension/Symbols/PSW_VersionCompare.cs b/src/PanelSwWixExtension/Symbols/PSW_VersionCompare.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_VersionCompare.cs rename to src/PanelSwWixExtension/Symbols/PSW_VersionCompare.cs diff --git a/PanelSwWixExtension/Symbols/PSW_WebsiteConfig.cs b/src/PanelSwWixExtension/Symbols/PSW_WebsiteConfig.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_WebsiteConfig.cs rename to src/PanelSwWixExtension/Symbols/PSW_WebsiteConfig.cs diff --git a/PanelSwWixExtension/Symbols/PSW_WmiSearch.cs b/src/PanelSwWixExtension/Symbols/PSW_WmiSearch.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_WmiSearch.cs rename to src/PanelSwWixExtension/Symbols/PSW_WmiSearch.cs diff --git a/PanelSwWixExtension/Symbols/PSW_XmlSearch.cs b/src/PanelSwWixExtension/Symbols/PSW_XmlSearch.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_XmlSearch.cs rename to src/PanelSwWixExtension/Symbols/PSW_XmlSearch.cs diff --git a/PanelSwWixExtension/Symbols/PSW_XslTransform.cs b/src/PanelSwWixExtension/Symbols/PSW_XslTransform.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_XslTransform.cs rename to src/PanelSwWixExtension/Symbols/PSW_XslTransform.cs diff --git a/PanelSwWixExtension/Symbols/PSW_XslTransform_Replacements.cs b/src/PanelSwWixExtension/Symbols/PSW_XslTransform_Replacements.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_XslTransform_Replacements.cs rename to src/PanelSwWixExtension/Symbols/PSW_XslTransform_Replacements.cs diff --git a/PanelSwWixExtension/Symbols/PSW_ZipFile.cs b/src/PanelSwWixExtension/Symbols/PSW_ZipFile.cs similarity index 100% rename from PanelSwWixExtension/Symbols/PSW_ZipFile.cs rename to src/PanelSwWixExtension/Symbols/PSW_ZipFile.cs diff --git a/PanelSwWixExtension/Xsd/PanelSwWixExtension.xsd b/src/PanelSwWixExtension/Xsd/PanelSwWixExtension.xsd similarity index 99% rename from PanelSwWixExtension/Xsd/PanelSwWixExtension.xsd rename to src/PanelSwWixExtension/Xsd/PanelSwWixExtension.xsd index 628c6860..90023c33 100644 --- a/PanelSwWixExtension/Xsd/PanelSwWixExtension.xsd +++ b/src/PanelSwWixExtension/Xsd/PanelSwWixExtension.xsd @@ -191,7 +191,7 @@ Maximal size of the payloads in the bundle executable. Allowed when DefaultType is attached - + Bundle container compression method. psw-wix only. Defaults to cab @@ -2343,8 +2343,9 @@ Call ShellExecuteEx with parameters Bundle container compression method. psw-wix only. - - + + + diff --git a/PanelSwWixHarvestExtension/PanelSwWixHarvestExtension.cs b/src/PanelSwWixHarvestExtension/PanelSwWixHarvestExtension.cs similarity index 100% rename from PanelSwWixHarvestExtension/PanelSwWixHarvestExtension.cs rename to src/PanelSwWixHarvestExtension/PanelSwWixHarvestExtension.cs diff --git a/PanelSwWixHarvestExtension/PanelSwWixHarvestExtension.csproj b/src/PanelSwWixHarvestExtension/PanelSwWixHarvestExtension.csproj similarity index 100% rename from PanelSwWixHarvestExtension/PanelSwWixHarvestExtension.csproj rename to src/PanelSwWixHarvestExtension/PanelSwWixHarvestExtension.csproj diff --git a/PanelSwWixHarvestExtension/PanelSwWixHarvestExtensionFactory.cs b/src/PanelSwWixHarvestExtension/PanelSwWixHarvestExtensionFactory.cs similarity index 100% rename from PanelSwWixHarvestExtension/PanelSwWixHarvestExtensionFactory.cs rename to src/PanelSwWixHarvestExtension/PanelSwWixHarvestExtensionFactory.cs diff --git a/ProtoCaLib/ProtoCaLib.vcxproj b/src/ProtoCaLib/ProtoCaLib.vcxproj similarity index 100% rename from ProtoCaLib/ProtoCaLib.vcxproj rename to src/ProtoCaLib/ProtoCaLib.vcxproj diff --git a/ProtoCaLib/ProtoCaLib.vcxproj.filters b/src/ProtoCaLib/ProtoCaLib.vcxproj.filters similarity index 100% rename from ProtoCaLib/ProtoCaLib.vcxproj.filters rename to src/ProtoCaLib/ProtoCaLib.vcxproj.filters diff --git a/ProtoCaLib/command.proto b/src/ProtoCaLib/command.proto similarity index 100% rename from ProtoCaLib/command.proto rename to src/ProtoCaLib/command.proto diff --git a/ProtoCaLib/concatFilesDetails.proto b/src/ProtoCaLib/concatFilesDetails.proto similarity index 100% rename from ProtoCaLib/concatFilesDetails.proto rename to src/ProtoCaLib/concatFilesDetails.proto diff --git a/ProtoCaLib/customActionData.proto b/src/ProtoCaLib/customActionData.proto similarity index 100% rename from ProtoCaLib/customActionData.proto rename to src/ProtoCaLib/customActionData.proto diff --git a/ProtoCaLib/errorHandling.proto b/src/ProtoCaLib/errorHandling.proto similarity index 100% rename from ProtoCaLib/errorHandling.proto rename to src/ProtoCaLib/errorHandling.proto diff --git a/ProtoCaLib/execOnDetails.proto b/src/ProtoCaLib/execOnDetails.proto similarity index 100% rename from ProtoCaLib/execOnDetails.proto rename to src/ProtoCaLib/execOnDetails.proto diff --git a/ProtoCaLib/fileOperationsDetails.proto b/src/ProtoCaLib/fileOperationsDetails.proto similarity index 100% rename from ProtoCaLib/fileOperationsDetails.proto rename to src/ProtoCaLib/fileOperationsDetails.proto diff --git a/ProtoCaLib/fileRegexDetails.proto b/src/ProtoCaLib/fileRegexDetails.proto similarity index 100% rename from ProtoCaLib/fileRegexDetails.proto rename to src/ProtoCaLib/fileRegexDetails.proto diff --git a/ProtoCaLib/obfuscatedString.proto b/src/ProtoCaLib/obfuscatedString.proto similarity index 100% rename from ProtoCaLib/obfuscatedString.proto rename to src/ProtoCaLib/obfuscatedString.proto diff --git a/ProtoCaLib/restartLocalResourcesDetails.proto b/src/ProtoCaLib/restartLocalResourcesDetails.proto similarity index 100% rename from ProtoCaLib/restartLocalResourcesDetails.proto rename to src/ProtoCaLib/restartLocalResourcesDetails.proto diff --git a/ProtoCaLib/servciceConfigDetails.proto b/src/ProtoCaLib/servciceConfigDetails.proto similarity index 100% rename from ProtoCaLib/servciceConfigDetails.proto rename to src/ProtoCaLib/servciceConfigDetails.proto diff --git a/ProtoCaLib/setPropertyFromPipeDetails.proto b/src/ProtoCaLib/setPropertyFromPipeDetails.proto similarity index 100% rename from ProtoCaLib/setPropertyFromPipeDetails.proto rename to src/ProtoCaLib/setPropertyFromPipeDetails.proto diff --git a/ProtoCaLib/shellExecDetails.proto b/src/ProtoCaLib/shellExecDetails.proto similarity index 100% rename from ProtoCaLib/shellExecDetails.proto rename to src/ProtoCaLib/shellExecDetails.proto diff --git a/ProtoCaLib/sqlScriptDetails.proto b/src/ProtoCaLib/sqlScriptDetails.proto similarity index 100% rename from ProtoCaLib/sqlScriptDetails.proto rename to src/ProtoCaLib/sqlScriptDetails.proto diff --git a/ProtoCaLib/taskSchedulerDetails.proto b/src/ProtoCaLib/taskSchedulerDetails.proto similarity index 100% rename from ProtoCaLib/taskSchedulerDetails.proto rename to src/ProtoCaLib/taskSchedulerDetails.proto diff --git a/ProtoCaLib/telemetryDetails.proto b/src/ProtoCaLib/telemetryDetails.proto similarity index 100% rename from ProtoCaLib/telemetryDetails.proto rename to src/ProtoCaLib/telemetryDetails.proto diff --git a/ProtoCaLib/topShelfServiceDetails.proto b/src/ProtoCaLib/topShelfServiceDetails.proto similarity index 100% rename from ProtoCaLib/topShelfServiceDetails.proto rename to src/ProtoCaLib/topShelfServiceDetails.proto diff --git a/ProtoCaLib/unzipDetails.proto b/src/ProtoCaLib/unzipDetails.proto similarity index 100% rename from ProtoCaLib/unzipDetails.proto rename to src/ProtoCaLib/unzipDetails.proto diff --git a/ProtoCaLib/xslTransformDetails.proto b/src/ProtoCaLib/xslTransformDetails.proto similarity index 100% rename from ProtoCaLib/xslTransformDetails.proto rename to src/ProtoCaLib/xslTransformDetails.proto diff --git a/ProtoCaLib/zipDetails.proto b/src/ProtoCaLib/zipDetails.proto similarity index 100% rename from ProtoCaLib/zipDetails.proto rename to src/ProtoCaLib/zipDetails.proto diff --git a/PswManagedCA/CustomAction.config b/src/PswManagedCA/CustomAction.config similarity index 100% rename from PswManagedCA/CustomAction.config rename to src/PswManagedCA/CustomAction.config diff --git a/PswManagedCA/InstallUtil.cs b/src/PswManagedCA/InstallUtil.cs similarity index 97% rename from PswManagedCA/InstallUtil.cs rename to src/PswManagedCA/InstallUtil.cs index 52c0a137..4efd12a0 100644 --- a/PswManagedCA/InstallUtil.cs +++ b/src/PswManagedCA/InstallUtil.cs @@ -1,486 +1,486 @@ -using WixToolset.Dtf.WindowsInstaller; -using PswManagedCA.Util; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Configuration.Install; -using System.IO; -using System.Xml.Serialization; -using System.Linq; -using System.ComponentModel; -using System.Reflection; - -namespace PswManagedCA -{ - public class InstallUtil - { - private List catalogs_ = new List(); - private static readonly int msidbComponentAttributes64bit = 0x100; - enum InstallUtil_Bitness - { - asComponent = 0, - x86 = 1, - x64 = 2 - } - - enum ServiceErrorCode - { - ERROR_SERVICE_DOES_NOT_EXIST = 1060, - ERROR_SERVICE_MARKED_FOR_DELETE = 1072, - ERROR_SERVICE_EXISTS = 1073, - } - - [CustomAction] - public static ActionResult InstallUtilSched(Session session) - { - AssemblyName me = typeof(JsonJPath).Assembly.GetName(); - session.Log($"Initialized from {me.Name} v{me.Version}"); - - InstallUtil all = new InstallUtil(); - - using (View installUtilView = session.Database.OpenView("SELECT `PSW_InstallUtil`.`File_`, `PSW_InstallUtil`.`Bitness`, `File`.`Component_`, `Component`.`Attributes`" - + " FROM `PSW_InstallUtil`, `File`, `Component`" - + " WHERE `PSW_InstallUtil`.`File_`=`File`.`File` AND `File`.`Component_`=`Component`.`Component`" - )) - { - installUtilView.Execute(null); - - foreach (Record installUtilRec in installUtilView) - { - using (installUtilRec) - { - InstallUtilCatalog ctlg = new InstallUtilCatalog(); - ctlg.FileId = installUtilRec[1] as string; - int explicitBitness = installUtilRec.GetInteger(2); - string component = installUtilRec[3] as string; - int componentAttr = installUtilRec.GetInteger(4); - - bool x64 = ((explicitBitness == (int)InstallUtil_Bitness.x64) - || ((explicitBitness == (int)InstallUtil_Bitness.asComponent) && (componentAttr & msidbComponentAttributes64bit) == msidbComponentAttributes64bit)); - - // Sanity checks - if (string.IsNullOrWhiteSpace(ctlg.FileId)) - { - session.Log("File_ not supplied"); - return ActionResult.Failure; - } - ComponentInfo ci = session.Components[component]; - if (ci == null) - { - session.Log("File '{0}' not present in package", ctlg.FileId); - return ActionResult.Failure; - } - // Path will be empty if component is not scheduled to do anything. We'll check that only if action is relevant. - ctlg.FilePath = session.Format(string.Format("[#{0}]", ctlg.FileId)); - ctlg.ComponentInfo = ci; - ctlg.X64 = x64; - - using (View argsView = session.Database.OpenView($"SELECT `Value` FROM `PSW_InstallUtil_Arg` WHERE `File_`='{ctlg.FileId}'")) - { - argsView.Execute(null); - - foreach (Record argRec in argsView) - { - using (argRec) - { - string arg = argRec[1] as string; - if (!string.IsNullOrWhiteSpace(arg)) - { - string obfuscated = session.Obfuscate(arg); - arg = session.Format(arg); - if (!string.IsNullOrWhiteSpace(arg)) - { - ctlg.Arguments.Add(arg); - ctlg.ObfuscatedArguments.Add(obfuscated); - } - } - } - } - } - - switch (ci.RequestState) - { - case InstallState.Absent: - case InstallState.Removed: - case InstallState.Default: - case InstallState.Local: - case InstallState.Source: - if (string.IsNullOrWhiteSpace(ctlg.FilePath)) - { - session.Log("Can't get target path for file '{0}'", ctlg.FileId); - return ActionResult.Failure; - } - session.Log($"Will configure InstallUtil service '{ctlg.FilePath}'"); - all.catalogs_.Add(ctlg); - break; - - default: - session.Log($"Component '{ci.Name}' action isn't install, repair or remove. Skipping InstallUtil for file '{ctlg.FileId}'"); - continue; - } - } - } - } - - // Install has rollback to uninstall - // Uninstall has rollback to install - // Repair has no rollbak - XmlSerializer srlz = new XmlSerializer(all.catalogs_.GetType()); - List temp = new List(); - - // Install + repair x86 - temp.AddRange(from c in all.catalogs_ - where (!c.X64 && (c.ComponentInfo.RequestState >= InstallState.Local)) - select c); - if (temp.Count() > 0) - { - foreach (InstallUtilCatalog c in temp) - { - c.Action = (c.ComponentInfo.CurrentState < InstallState.Local) ? InstallUtilCatalog.InstallUtilAction.Install : InstallUtilCatalog.InstallUtilAction.Reinstall; - } - temp = new List(temp.Distinct()); - using (StringWriter sw = new StringWriter()) - { - srlz.Serialize(sw, temp); - session["PSW_InstallUtil_InstallExec_x86"] = sw.ToString(); - } - } - // Rollback of install x86 - temp.Clear(); - temp.AddRange(from c in all.catalogs_ - where (!c.X64 && ((c.ComponentInfo.RequestState >= InstallState.Local) && (c.ComponentInfo.CurrentState < InstallState.Local))) - select c); - if (temp.Count() > 0) - { - foreach (InstallUtilCatalog c in temp) - { - c.Action = InstallUtilCatalog.InstallUtilAction.Uninstall; - } - temp = new List(temp.Distinct()); - using (StringWriter sw = new StringWriter()) - { - srlz.Serialize(sw, temp); - session["PSW_InstallUtil_InstallRollback_x86"] = sw.ToString(); - } - } - // Install + repair x64 - temp.Clear(); - temp.AddRange(from c in all.catalogs_ - where (c.X64 && (c.ComponentInfo.RequestState >= InstallState.Local)) - select c); - if (temp.Count() > 0) - { - foreach (InstallUtilCatalog c in temp) - { - c.Action = (c.ComponentInfo.CurrentState < InstallState.Local) ? InstallUtilCatalog.InstallUtilAction.Install : InstallUtilCatalog.InstallUtilAction.Reinstall; - } - temp = new List(temp.Distinct()); - using (StringWriter sw = new StringWriter()) - { - srlz.Serialize(sw, temp); - session["PSW_InstallUtil_InstallExec_x64"] = sw.ToString(); - } - } - // Rollback of install x64 - temp.Clear(); - temp.AddRange(from c in all.catalogs_ - where (c.X64 && ((c.ComponentInfo.RequestState >= InstallState.Local) && (c.ComponentInfo.CurrentState < InstallState.Local))) - select c); - if (temp.Count() > 0) - { - foreach (InstallUtilCatalog c in temp) - { - c.Action = InstallUtilCatalog.InstallUtilAction.Uninstall; - } - temp = new List(temp.Distinct()); - using (StringWriter sw = new StringWriter()) - { - srlz.Serialize(sw, temp); - session["PSW_InstallUtil_InstallRollback_x64"] = sw.ToString(); - } - } - - // UnInstall x86 - temp.Clear(); - temp.AddRange(from c in all.catalogs_ - where (!c.X64 && (c.ComponentInfo.CurrentState >= InstallState.Local) && (c.ComponentInfo.RequestState < InstallState.Local)) - select c); - if (temp.Count() > 0) - { - foreach (InstallUtilCatalog c in temp) - { - c.Action = InstallUtilCatalog.InstallUtilAction.Uninstall; - } - temp = new List(temp.Distinct()); - using (StringWriter sw = new StringWriter()) - { - srlz.Serialize(sw, temp); - session["PSW_InstallUtil_UninstallExec_x86"] = sw.ToString(); - } - foreach (InstallUtilCatalog c in temp) - { - c.Action = InstallUtilCatalog.InstallUtilAction.Install; - } - using (StringWriter sw = new StringWriter()) - { - srlz.Serialize(sw, temp); - session["PSW_InstallUtil_UninstallRollback_x86"] = sw.ToString(); - } - } - // UnInstall x64 - temp.Clear(); - temp.AddRange(from c in all.catalogs_ - where (c.X64 && (c.ComponentInfo.CurrentState >= InstallState.Local) && (c.ComponentInfo.RequestState < InstallState.Local)) - select c); - if (temp.Count() > 0) - { - foreach (InstallUtilCatalog c in temp) - { - c.Action = InstallUtilCatalog.InstallUtilAction.Uninstall; - } - temp = new List(temp.Distinct()); - using (StringWriter sw = new StringWriter()) - { - srlz.Serialize(sw, temp); - session["PSW_InstallUtil_UninstallExec_x64"] = sw.ToString(); - } - foreach (InstallUtilCatalog c in temp) - { - c.Action = InstallUtilCatalog.InstallUtilAction.Install; - } - using (StringWriter sw = new StringWriter()) - { - srlz.Serialize(sw, temp); - session["PSW_InstallUtil_UninstallRollback_x64"] = sw.ToString(); - } - } - - return ActionResult.Success; - } - - /// - /// Deferred execution of InstallUtil. - /// This is the entry point for all InstallUtil actions (install, remove and their respective rollback). - /// - /// - /// - [CustomAction] - public static ActionResult InstallUtilExec(Session session) - { - AssemblyName me = typeof(JsonJPath).Assembly.GetName(); - session.Log($"Initialized from {me.Name} v{me.Version}"); - - InstallUtil executer = new InstallUtil(); - - XmlSerializer srlz = new XmlSerializer(executer.catalogs_.GetType()); - string cad = session["CustomActionData"]; - if (string.IsNullOrWhiteSpace(cad)) - { - session.Log("Nothing to do"); - return ActionResult.Success; - } - - using (StringReader sr = new StringReader(cad)) - { - if (srlz.Deserialize(sr) is IEnumerable ctlgs) - { - executer.catalogs_.AddRange(ctlgs); - } - } - executer.Execute(session); - - return ActionResult.Success; - } - - private void Execute(Session session) - { - session.Log($"Configuring {catalogs_.Count} InstallUtil services"); - foreach (InstallUtilCatalog ctlg in catalogs_) - { - // Temporary file for logging - string tmpFile = Path.GetTempFileName(); - IDictionary savedState = new Hashtable(); - - try - { - // (Un)Install the assembly - if (ctlg.ObfuscatedArguments.Count > 0) - { - session.Log($"Applying {ctlg.Action} on assembly '{ctlg.FilePath}' with arguments {ctlg.ObfuscatedArguments.Aggregate((a, c) => $"{a}, {c}")}"); - } - else - { - session.Log($"Applying {ctlg.Action} on assembly '{ctlg.FilePath}'"); - } - - ctlg.Arguments.Add($"/LogFile={tmpFile}"); - ctlg.Arguments.Add("/LogToConsole=false"); - - AssemblyInstaller installer = new AssemblyInstaller(ctlg.FilePath, ctlg.Arguments.ToArray()); - installer.UseNewContext = true; - - switch (ctlg.Action) - { - case InstallUtilCatalog.InstallUtilAction.Install: - case InstallUtilCatalog.InstallUtilAction.Reinstall: - installer.Install(savedState); - installer.Commit(savedState); - break; - - case InstallUtilCatalog.InstallUtilAction.Uninstall: - installer.Uninstall(savedState); - break; - } - } - catch (Win32Exception ex) - { - // Ignore if: - // - Deleting and service doesn't exist - // - Deleting and service is marked for delete - // - Repairing and service is already installed - switch (ex.NativeErrorCode) - { - case (int)ServiceErrorCode.ERROR_SERVICE_DOES_NOT_EXIST: - if (ctlg.Action != InstallUtilCatalog.InstallUtilAction.Uninstall) - { - session.Log($"Exception with code {ex.ErrorCode} (native {ex.NativeErrorCode}): {ex}"); - throw; - } - session.Log($"Service {ctlg.FilePath} is not installed anyway"); - break; - - case (int)ServiceErrorCode.ERROR_SERVICE_EXISTS: - if (ctlg.Action != InstallUtilCatalog.InstallUtilAction.Reinstall) - { - session.Log($"Exception with code {ex.ErrorCode} (native {ex.NativeErrorCode}): {ex}"); - throw; - } - session.Log($"Service {ctlg.FilePath} is already installed"); - break; - - case (int)ServiceErrorCode.ERROR_SERVICE_MARKED_FOR_DELETE: - if (ctlg.Action != InstallUtilCatalog.InstallUtilAction.Uninstall) - { - session.Log($"Exception with code {ex.ErrorCode} (native {ex.NativeErrorCode}): {ex}"); - throw; - } - session.Log($"Service {ctlg.FilePath} is already marked for delete"); - break; - - default: - session.Log($"Exception with code {ex.ErrorCode} (native {ex.NativeErrorCode}): {ex}"); - throw; - } - } - catch (InstallException ex) - { - if ((ex.InnerException == null) || !(ex.InnerException is Win32Exception wex)) - { - throw; - } - - // Ignore if: - // - Deleting and service doesn't exist - // - Deleting and service is marked for delete - // - Repairing and service is already installed - switch (wex.NativeErrorCode) - { - case (int)ServiceErrorCode.ERROR_SERVICE_DOES_NOT_EXIST: - if (ctlg.Action != InstallUtilCatalog.InstallUtilAction.Uninstall) - { - session.Log($"Exception with code {wex.ErrorCode} (native {wex.NativeErrorCode}): {ex}"); - throw; - } - session.Log($"Service {ctlg.FilePath} is not installed anyway"); - break; - - case (int)ServiceErrorCode.ERROR_SERVICE_EXISTS: - if (ctlg.Action != InstallUtilCatalog.InstallUtilAction.Reinstall) - { - session.Log($"Exception with code {wex.ErrorCode} (native {wex.NativeErrorCode}): {ex}"); - throw; - } - session.Log($"Service {ctlg.FilePath} is already installed"); - break; - - case (int)ServiceErrorCode.ERROR_SERVICE_MARKED_FOR_DELETE: - if (ctlg.Action != InstallUtilCatalog.InstallUtilAction.Uninstall) - { - session.Log($"Exception with code {wex.ErrorCode} (native {wex.NativeErrorCode}): {ex}"); - throw; - } - session.Log($"Service {ctlg.FilePath} is already marked for delete"); - break; - - default: - session.Log($"Exception with code {wex.ErrorCode} (native {wex.NativeErrorCode}): {ex}"); - throw; - } - } - finally - { - // Dump and clear log - try - { - if (File.Exists(tmpFile)) - { - session.Log(File.ReadAllText(tmpFile)); - File.Delete(tmpFile); - } - } - catch { } - } - } - } - - [Serializable] - public class InstallUtilCatalog - { - public InstallUtilCatalog() - { - Arguments = new List(); - ObfuscatedArguments = new List(); - } - - public enum InstallUtilAction - { - Install, - Reinstall, - Uninstall - } - - public InstallUtilAction Action { get; set; } - - public List Arguments { get; set; } - - public List ObfuscatedArguments { get; set; } - - public string FileId { get; set; } - - public string FilePath { get; set; } - - [XmlIgnore] - public ComponentInfo ComponentInfo { get; set; } - - [XmlIgnore] - public bool X64 { get; set; } - - public override bool Equals(object obj) - { - if (obj is InstallUtilCatalog ctlg) - { - return Action.Equals(ctlg.Action) - && Arguments.SequenceEqual(ctlg.Arguments) - && FilePath.Equals(ctlg.FilePath) - && (X64 == ctlg.X64); - } - return false; - } - - public override int GetHashCode() - { - return FilePath.GetHashCode(); - } - } - } -} +using WixToolset.Dtf.WindowsInstaller; +using PswManagedCA.Util; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Configuration.Install; +using System.IO; +using System.Xml.Serialization; +using System.Linq; +using System.ComponentModel; +using System.Reflection; + +namespace PswManagedCA +{ + public class InstallUtil + { + private List catalogs_ = new List(); + private static readonly int msidbComponentAttributes64bit = 0x100; + enum InstallUtil_Bitness + { + asComponent = 0, + x86 = 1, + x64 = 2 + } + + enum ServiceErrorCode + { + ERROR_SERVICE_DOES_NOT_EXIST = 1060, + ERROR_SERVICE_MARKED_FOR_DELETE = 1072, + ERROR_SERVICE_EXISTS = 1073, + } + + [CustomAction] + public static ActionResult InstallUtilSched(Session session) + { + AssemblyName me = typeof(JsonJPath).Assembly.GetName(); + session.Log($"Initialized from {me.Name} v{me.Version}"); + + InstallUtil all = new InstallUtil(); + + using (View installUtilView = session.Database.OpenView("SELECT `PSW_InstallUtil`.`File_`, `PSW_InstallUtil`.`Bitness`, `File`.`Component_`, `Component`.`Attributes`" + + " FROM `PSW_InstallUtil`, `File`, `Component`" + + " WHERE `PSW_InstallUtil`.`File_`=`File`.`File` AND `File`.`Component_`=`Component`.`Component`" + )) + { + installUtilView.Execute(null); + + foreach (Record installUtilRec in installUtilView) + { + using (installUtilRec) + { + InstallUtilCatalog ctlg = new InstallUtilCatalog(); + ctlg.FileId = installUtilRec[1] as string; + int explicitBitness = installUtilRec.GetInteger(2); + string component = installUtilRec[3] as string; + int componentAttr = installUtilRec.GetInteger(4); + + bool x64 = ((explicitBitness == (int)InstallUtil_Bitness.x64) + || ((explicitBitness == (int)InstallUtil_Bitness.asComponent) && (componentAttr & msidbComponentAttributes64bit) == msidbComponentAttributes64bit)); + + // Sanity checks + if (string.IsNullOrWhiteSpace(ctlg.FileId)) + { + session.Log("File_ not supplied"); + return ActionResult.Failure; + } + ComponentInfo ci = session.Components[component]; + if (ci == null) + { + session.Log("File '{0}' not present in package", ctlg.FileId); + return ActionResult.Failure; + } + // Path will be empty if component is not scheduled to do anything. We'll check that only if action is relevant. + ctlg.FilePath = session.Format(string.Format("[#{0}]", ctlg.FileId)); + ctlg.ComponentInfo = ci; + ctlg.X64 = x64; + + using (View argsView = session.Database.OpenView($"SELECT `Value` FROM `PSW_InstallUtil_Arg` WHERE `File_`='{ctlg.FileId}'")) + { + argsView.Execute(null); + + foreach (Record argRec in argsView) + { + using (argRec) + { + string arg = argRec[1] as string; + if (!string.IsNullOrWhiteSpace(arg)) + { + string obfuscated = session.Obfuscate(arg); + arg = session.Format(arg); + if (!string.IsNullOrWhiteSpace(arg)) + { + ctlg.Arguments.Add(arg); + ctlg.ObfuscatedArguments.Add(obfuscated); + } + } + } + } + } + + switch (ci.RequestState) + { + case InstallState.Absent: + case InstallState.Removed: + case InstallState.Default: + case InstallState.Local: + case InstallState.Source: + if (string.IsNullOrWhiteSpace(ctlg.FilePath)) + { + session.Log("Can't get target path for file '{0}'", ctlg.FileId); + return ActionResult.Failure; + } + session.Log($"Will configure InstallUtil service '{ctlg.FilePath}'"); + all.catalogs_.Add(ctlg); + break; + + default: + session.Log($"Component '{ci.Name}' action isn't install, repair or remove. Skipping InstallUtil for file '{ctlg.FileId}'"); + continue; + } + } + } + } + + // Install has rollback to uninstall + // Uninstall has rollback to install + // Repair has no rollbak + XmlSerializer srlz = new XmlSerializer(all.catalogs_.GetType()); + List temp = new List(); + + // Install + repair x86 + temp.AddRange(from c in all.catalogs_ + where (!c.X64 && (c.ComponentInfo.RequestState >= InstallState.Local)) + select c); + if (temp.Count() > 0) + { + foreach (InstallUtilCatalog c in temp) + { + c.Action = (c.ComponentInfo.CurrentState < InstallState.Local) ? InstallUtilCatalog.InstallUtilAction.Install : InstallUtilCatalog.InstallUtilAction.Reinstall; + } + temp = new List(temp.Distinct()); + using (StringWriter sw = new StringWriter()) + { + srlz.Serialize(sw, temp); + session["PSW_InstallUtil_InstallExec_x86"] = sw.ToString(); + } + } + // Rollback of install x86 + temp.Clear(); + temp.AddRange(from c in all.catalogs_ + where (!c.X64 && ((c.ComponentInfo.RequestState >= InstallState.Local) && (c.ComponentInfo.CurrentState < InstallState.Local))) + select c); + if (temp.Count() > 0) + { + foreach (InstallUtilCatalog c in temp) + { + c.Action = InstallUtilCatalog.InstallUtilAction.Uninstall; + } + temp = new List(temp.Distinct()); + using (StringWriter sw = new StringWriter()) + { + srlz.Serialize(sw, temp); + session["PSW_InstallUtil_InstallRollback_x86"] = sw.ToString(); + } + } + // Install + repair x64 + temp.Clear(); + temp.AddRange(from c in all.catalogs_ + where (c.X64 && (c.ComponentInfo.RequestState >= InstallState.Local)) + select c); + if (temp.Count() > 0) + { + foreach (InstallUtilCatalog c in temp) + { + c.Action = (c.ComponentInfo.CurrentState < InstallState.Local) ? InstallUtilCatalog.InstallUtilAction.Install : InstallUtilCatalog.InstallUtilAction.Reinstall; + } + temp = new List(temp.Distinct()); + using (StringWriter sw = new StringWriter()) + { + srlz.Serialize(sw, temp); + session["PSW_InstallUtil_InstallExec_x64"] = sw.ToString(); + } + } + // Rollback of install x64 + temp.Clear(); + temp.AddRange(from c in all.catalogs_ + where (c.X64 && ((c.ComponentInfo.RequestState >= InstallState.Local) && (c.ComponentInfo.CurrentState < InstallState.Local))) + select c); + if (temp.Count() > 0) + { + foreach (InstallUtilCatalog c in temp) + { + c.Action = InstallUtilCatalog.InstallUtilAction.Uninstall; + } + temp = new List(temp.Distinct()); + using (StringWriter sw = new StringWriter()) + { + srlz.Serialize(sw, temp); + session["PSW_InstallUtil_InstallRollback_x64"] = sw.ToString(); + } + } + + // UnInstall x86 + temp.Clear(); + temp.AddRange(from c in all.catalogs_ + where (!c.X64 && (c.ComponentInfo.CurrentState >= InstallState.Local) && (c.ComponentInfo.RequestState < InstallState.Local)) + select c); + if (temp.Count() > 0) + { + foreach (InstallUtilCatalog c in temp) + { + c.Action = InstallUtilCatalog.InstallUtilAction.Uninstall; + } + temp = new List(temp.Distinct()); + using (StringWriter sw = new StringWriter()) + { + srlz.Serialize(sw, temp); + session["PSW_InstallUtil_UninstallExec_x86"] = sw.ToString(); + } + foreach (InstallUtilCatalog c in temp) + { + c.Action = InstallUtilCatalog.InstallUtilAction.Install; + } + using (StringWriter sw = new StringWriter()) + { + srlz.Serialize(sw, temp); + session["PSW_InstallUtil_UninstallRollback_x86"] = sw.ToString(); + } + } + // UnInstall x64 + temp.Clear(); + temp.AddRange(from c in all.catalogs_ + where (c.X64 && (c.ComponentInfo.CurrentState >= InstallState.Local) && (c.ComponentInfo.RequestState < InstallState.Local)) + select c); + if (temp.Count() > 0) + { + foreach (InstallUtilCatalog c in temp) + { + c.Action = InstallUtilCatalog.InstallUtilAction.Uninstall; + } + temp = new List(temp.Distinct()); + using (StringWriter sw = new StringWriter()) + { + srlz.Serialize(sw, temp); + session["PSW_InstallUtil_UninstallExec_x64"] = sw.ToString(); + } + foreach (InstallUtilCatalog c in temp) + { + c.Action = InstallUtilCatalog.InstallUtilAction.Install; + } + using (StringWriter sw = new StringWriter()) + { + srlz.Serialize(sw, temp); + session["PSW_InstallUtil_UninstallRollback_x64"] = sw.ToString(); + } + } + + return ActionResult.Success; + } + + /// + /// Deferred execution of InstallUtil. + /// This is the entry point for all InstallUtil actions (install, remove and their respective rollback). + /// + /// + /// + [CustomAction] + public static ActionResult InstallUtilExec(Session session) + { + AssemblyName me = typeof(JsonJPath).Assembly.GetName(); + session.Log($"Initialized from {me.Name} v{me.Version}"); + + InstallUtil executer = new InstallUtil(); + + XmlSerializer srlz = new XmlSerializer(executer.catalogs_.GetType()); + string cad = session["CustomActionData"]; + if (string.IsNullOrWhiteSpace(cad)) + { + session.Log("Nothing to do"); + return ActionResult.Success; + } + + using (StringReader sr = new StringReader(cad)) + { + if (srlz.Deserialize(sr) is IEnumerable ctlgs) + { + executer.catalogs_.AddRange(ctlgs); + } + } + executer.Execute(session); + + return ActionResult.Success; + } + + private void Execute(Session session) + { + session.Log($"Configuring {catalogs_.Count} InstallUtil services"); + foreach (InstallUtilCatalog ctlg in catalogs_) + { + // Temporary file for logging + string tmpFile = Path.GetTempFileName(); + IDictionary savedState = new Hashtable(); + + try + { + // (Un)Install the assembly + if (ctlg.ObfuscatedArguments.Count > 0) + { + session.Log($"Applying {ctlg.Action} on assembly '{ctlg.FilePath}' with arguments {ctlg.ObfuscatedArguments.Aggregate((a, c) => $"{a}, {c}")}"); + } + else + { + session.Log($"Applying {ctlg.Action} on assembly '{ctlg.FilePath}'"); + } + + ctlg.Arguments.Add($"/LogFile={tmpFile}"); + ctlg.Arguments.Add("/LogToConsole=false"); + + AssemblyInstaller installer = new AssemblyInstaller(ctlg.FilePath, ctlg.Arguments.ToArray()); + installer.UseNewContext = true; + + switch (ctlg.Action) + { + case InstallUtilCatalog.InstallUtilAction.Install: + case InstallUtilCatalog.InstallUtilAction.Reinstall: + installer.Install(savedState); + installer.Commit(savedState); + break; + + case InstallUtilCatalog.InstallUtilAction.Uninstall: + installer.Uninstall(savedState); + break; + } + } + catch (Win32Exception ex) + { + // Ignore if: + // - Deleting and service doesn't exist + // - Deleting and service is marked for delete + // - Repairing and service is already installed + switch (ex.NativeErrorCode) + { + case (int)ServiceErrorCode.ERROR_SERVICE_DOES_NOT_EXIST: + if (ctlg.Action != InstallUtilCatalog.InstallUtilAction.Uninstall) + { + session.Log($"Exception with code {ex.ErrorCode} (native {ex.NativeErrorCode}): {ex}"); + throw; + } + session.Log($"Service {ctlg.FilePath} is not installed anyway"); + break; + + case (int)ServiceErrorCode.ERROR_SERVICE_EXISTS: + if (ctlg.Action != InstallUtilCatalog.InstallUtilAction.Reinstall) + { + session.Log($"Exception with code {ex.ErrorCode} (native {ex.NativeErrorCode}): {ex}"); + throw; + } + session.Log($"Service {ctlg.FilePath} is already installed"); + break; + + case (int)ServiceErrorCode.ERROR_SERVICE_MARKED_FOR_DELETE: + if (ctlg.Action != InstallUtilCatalog.InstallUtilAction.Uninstall) + { + session.Log($"Exception with code {ex.ErrorCode} (native {ex.NativeErrorCode}): {ex}"); + throw; + } + session.Log($"Service {ctlg.FilePath} is already marked for delete"); + break; + + default: + session.Log($"Exception with code {ex.ErrorCode} (native {ex.NativeErrorCode}): {ex}"); + throw; + } + } + catch (InstallException ex) + { + if ((ex.InnerException == null) || !(ex.InnerException is Win32Exception wex)) + { + throw; + } + + // Ignore if: + // - Deleting and service doesn't exist + // - Deleting and service is marked for delete + // - Repairing and service is already installed + switch (wex.NativeErrorCode) + { + case (int)ServiceErrorCode.ERROR_SERVICE_DOES_NOT_EXIST: + if (ctlg.Action != InstallUtilCatalog.InstallUtilAction.Uninstall) + { + session.Log($"Exception with code {wex.ErrorCode} (native {wex.NativeErrorCode}): {ex}"); + throw; + } + session.Log($"Service {ctlg.FilePath} is not installed anyway"); + break; + + case (int)ServiceErrorCode.ERROR_SERVICE_EXISTS: + if (ctlg.Action != InstallUtilCatalog.InstallUtilAction.Reinstall) + { + session.Log($"Exception with code {wex.ErrorCode} (native {wex.NativeErrorCode}): {ex}"); + throw; + } + session.Log($"Service {ctlg.FilePath} is already installed"); + break; + + case (int)ServiceErrorCode.ERROR_SERVICE_MARKED_FOR_DELETE: + if (ctlg.Action != InstallUtilCatalog.InstallUtilAction.Uninstall) + { + session.Log($"Exception with code {wex.ErrorCode} (native {wex.NativeErrorCode}): {ex}"); + throw; + } + session.Log($"Service {ctlg.FilePath} is already marked for delete"); + break; + + default: + session.Log($"Exception with code {wex.ErrorCode} (native {wex.NativeErrorCode}): {ex}"); + throw; + } + } + finally + { + // Dump and clear log + try + { + if (File.Exists(tmpFile)) + { + session.Log(File.ReadAllText(tmpFile)); + File.Delete(tmpFile); + } + } + catch { } + } + } + } + + [Serializable] + public class InstallUtilCatalog + { + public InstallUtilCatalog() + { + Arguments = new List(); + ObfuscatedArguments = new List(); + } + + public enum InstallUtilAction + { + Install, + Reinstall, + Uninstall + } + + public InstallUtilAction Action { get; set; } + + public List Arguments { get; set; } + + public List ObfuscatedArguments { get; set; } + + public string FileId { get; set; } + + public string FilePath { get; set; } + + [XmlIgnore] + public ComponentInfo ComponentInfo { get; set; } + + [XmlIgnore] + public bool X64 { get; set; } + + public override bool Equals(object obj) + { + if (obj is InstallUtilCatalog ctlg) + { + return Action.Equals(ctlg.Action) + && Arguments.SequenceEqual(ctlg.Arguments) + && FilePath.Equals(ctlg.FilePath) + && (X64 == ctlg.X64); + } + return false; + } + + public override int GetHashCode() + { + return FilePath.GetHashCode(); + } + } + } +} diff --git a/PswManagedCA/JsonJPath.cs b/src/PswManagedCA/JsonJPath.cs similarity index 100% rename from PswManagedCA/JsonJPath.cs rename to src/PswManagedCA/JsonJPath.cs diff --git a/PswManagedCA/PswManagedCA.csproj b/src/PswManagedCA/PswManagedCA.csproj similarity index 96% rename from PswManagedCA/PswManagedCA.csproj rename to src/PswManagedCA/PswManagedCA.csproj index bb346ab8..1a81d247 100644 --- a/PswManagedCA/PswManagedCA.csproj +++ b/src/PswManagedCA/PswManagedCA.csproj @@ -1,23 +1,23 @@ - - - net472 - x86;x64 - PswManagedCA - - - - - - - - - - - - - - - - - - + + + net472 + x86;x64 + PswManagedCA + + + + + + + + + + + + + + + + + + diff --git a/PswManagedCA/Util/SessionEx.cs b/src/PswManagedCA/Util/SessionEx.cs similarity index 96% rename from PswManagedCA/Util/SessionEx.cs rename to src/PswManagedCA/Util/SessionEx.cs index 97116431..8475a2e7 100644 --- a/PswManagedCA/Util/SessionEx.cs +++ b/src/PswManagedCA/Util/SessionEx.cs @@ -1,113 +1,113 @@ -using WixToolset.Dtf.WindowsInstaller; -using System; - -namespace PswManagedCA.Util -{ - public enum ErrorHandling - { - fail = 0, - ignore = 1, - prompt = 2 - } - - public enum PswErrorMessages - { - TopShelfFailure = 27000, - ExecOnFailure = 27001, - ServiceConfigFailure = 27002, - DismPackageFailure = 27003, - DismFeatureFailure = 27004, - SqlScriptFailure = 27005, - ExecOnConsoleFailure = 27006, - WebsiteConfigFailure = 27007, - SqlSearchFailure = 27008, - JsonJpathFailure = 27009, - DismUnwantedFeatureFailure = 27010, - ExecOnPromptAlways = 27011, - PromptFileDowngrades = 27012, - ZipFileError = 27013, - ZipArchiveError = 27014, - UnzipArchiveError = 27015, - UnzipFileeError = 27016, - } - - static class SessionEx - { - public static ComponentInfo ComponentByFileId(this Session session, string fileId) - { - using (View view = session.Database.OpenView("SELECT `Component_` FROM `File` WHERE `File`='{0}'", fileId)) - { - view.Execute(null); - foreach (Record rec in view) - { - using (rec) - { - string comp = rec[1] as string; - - return session.Components[comp]; - } - } - } - - return null; - } - - public static string Obfuscate(this Session session, string msg) - { - string[] hiddenProps = session["MsiHiddenProperties"] - .Split(new char[] {';'}, StringSplitOptions.RemoveEmptyEntries); - foreach (string p in hiddenProps) - { - msg = msg.Replace($"[{p}]", "******"); - } - - return session.Format(msg); - } - - public static void LogObfuscated(this Session session, string msg) - { - msg = session.Obfuscate(msg); - session.LogUnformatted(msg); - } - - public static void LogUnformatted(this Session session, string msg) - { - using (Record rec = new Record(1)) - { - rec.FormatString = "[1]"; - rec[1] = msg; - session.Message(InstallMessage.Info, rec); - } - } - - public static MessageResult HandleError(this Session session, ErrorHandling errorHandling, int errCode, params object[] prms) - { - switch (errorHandling) - { - default: // Silent / fail - return MessageResult.Abort; - - case ErrorHandling.ignore: - return MessageResult.Ignore; - - case ErrorHandling.prompt: - break; - } - - using (Record rec = new Record(2 + (prms?.Length ?? 1))) - { - rec[1] = errCode; - if (prms != null) - { - for (int i = 0; i < prms.Length; ++i) - { - rec[i + 2] = prms[i]; - } - } - - int hint = (int)InstallMessage.Error | (int)MessageButtons.AbortRetryIgnore | (int)MessageDefaultButton.Button1 | (int)MessageIcon.Error; - return session.Message((InstallMessage)hint, rec); - } - } - } -} +using WixToolset.Dtf.WindowsInstaller; +using System; + +namespace PswManagedCA.Util +{ + public enum ErrorHandling + { + fail = 0, + ignore = 1, + prompt = 2 + } + + public enum PswErrorMessages + { + TopShelfFailure = 27000, + ExecOnFailure = 27001, + ServiceConfigFailure = 27002, + DismPackageFailure = 27003, + DismFeatureFailure = 27004, + SqlScriptFailure = 27005, + ExecOnConsoleFailure = 27006, + WebsiteConfigFailure = 27007, + SqlSearchFailure = 27008, + JsonJpathFailure = 27009, + DismUnwantedFeatureFailure = 27010, + ExecOnPromptAlways = 27011, + PromptFileDowngrades = 27012, + ZipFileError = 27013, + ZipArchiveError = 27014, + UnzipArchiveError = 27015, + UnzipFileeError = 27016, + } + + static class SessionEx + { + public static ComponentInfo ComponentByFileId(this Session session, string fileId) + { + using (View view = session.Database.OpenView("SELECT `Component_` FROM `File` WHERE `File`='{0}'", fileId)) + { + view.Execute(null); + foreach (Record rec in view) + { + using (rec) + { + string comp = rec[1] as string; + + return session.Components[comp]; + } + } + } + + return null; + } + + public static string Obfuscate(this Session session, string msg) + { + string[] hiddenProps = session["MsiHiddenProperties"] + .Split(new char[] {';'}, StringSplitOptions.RemoveEmptyEntries); + foreach (string p in hiddenProps) + { + msg = msg.Replace($"[{p}]", "******"); + } + + return session.Format(msg); + } + + public static void LogObfuscated(this Session session, string msg) + { + msg = session.Obfuscate(msg); + session.LogUnformatted(msg); + } + + public static void LogUnformatted(this Session session, string msg) + { + using (Record rec = new Record(1)) + { + rec.FormatString = "[1]"; + rec[1] = msg; + session.Message(InstallMessage.Info, rec); + } + } + + public static MessageResult HandleError(this Session session, ErrorHandling errorHandling, int errCode, params object[] prms) + { + switch (errorHandling) + { + default: // Silent / fail + return MessageResult.Abort; + + case ErrorHandling.ignore: + return MessageResult.Ignore; + + case ErrorHandling.prompt: + break; + } + + using (Record rec = new Record(2 + (prms?.Length ?? 1))) + { + rec[1] = errCode; + if (prms != null) + { + for (int i = 0; i < prms.Length; ++i) + { + rec[i + 2] = prms[i]; + } + } + + int hint = (int)InstallMessage.Error | (int)MessageButtons.AbortRetryIgnore | (int)MessageDefaultButton.Button1 | (int)MessageIcon.Error; + return session.Message((InstallMessage)hint, rec); + } + } + } +} diff --git a/PswManagedCA/WebsiteConfig.cs b/src/PswManagedCA/WebsiteConfig.cs similarity index 100% rename from PswManagedCA/WebsiteConfig.cs rename to src/PswManagedCA/WebsiteConfig.cs diff --git a/README.md b/src/README.md similarity index 98% rename from README.md rename to src/README.md index 0ab8d33c..1bf7464d 100644 --- a/README.md +++ b/src/README.md @@ -1,217 +1,218 @@ -[![PanelSwWixExtension](https://github.com/nirbar/PanelSwWixExtension/actions/workflows/github-actions-build.yml/badge.svg?branch=master4)](https://github.com/nirbar/PanelSwWixExtension/actions/workflows/github-actions-build.yml) -WiX v3 [![NuGet version (PanelSwWixExtension)](https://img.shields.io/nuget/v/PanelSwWixExtension.svg?style=flat-square)](https://www.nuget.org/packages/PanelSwWixExtension/) -WiX v4 [![NuGet version (PanelSwWixExtension4)](https://img.shields.io/nuget/v/PanelSwWixExtension4.svg?style=flat-square)](https://www.nuget.org/packages/PanelSwWixExtension4/) - -PanelSwWixExtension from the creator of [JetBA](https://github.com/nirbar/JetBA-Binaries) is the most comprehensive open source [WiX](http://wixtoolset.org/) extension. -I would like to thank JetBrains for their [support](https://www.jetbrains.com/community/opensource/) of this project - -## PanelSwWixExtension WiX Elements - -- Bundle elements: - - *ContainerTemplate*: A container template to which bundle payloads can be assigned - - *!(bindpath.PanelSwWixExtension)\x86\DeferredExePackage.exe* An executable that can execute arbitrary commands during chain execution - - Use InstallArguments='--skip-until-here "[SomeExecutable]" "arg1" "arg2"': Create a process with any arguments after the `--skip-until-here` part - - Use InstallArguments='--ignore-me': Ignore anything after the `--ignore-me` part -- Heat extension command line arguments: - - *-inc*: Semicolon seperated list of filename to include. Wildcards are accepted. If specified, any file not matching the pattern will be excluded - - *-exc*: Semicolon seperated list of filename to exclude. Wildcards are accepted. If specified, any file matching the pattern will be excluded - - *-prd*: Payload Root Folder. A prefix folder to add to all payloads -- Immediate Actions: - - *DuplicateFolder*: Duplicate an entire folder hierarchy. Processed at build time by adding entries to Directory, CreateFolder and DuplicateFile tables. - - *IsWindowsVersionOrGreater*: Test whether Kernel32.dll's version is at least the given version. If yes, set the property to 1. - - *Md5Hash*: Computes MD5 hash. - - *WmiSearch*: Execute a WMI query. - - *PathSearch*: Search for a file on PATH environment variable folder list. - - *VersionCompare*: Compare two versions, set result to property to value in range -4 to +4, denoting the version part that was different (-+4 if Major part was different, -+3 for Minor part, etc.) - - *ForceVersion*: Force a specified version for a file. Version overwrite is done on runtime in the MSI database. - - *AccountSidSearch*: Lookup an account's SID by account name. - - *JsonJpathSearch*: Read JSON values - - *DiskSpace*: Calculate available disk space for a target directory - - *CertificateHashSearch*: Find a certificate hash in local system MY store. - - *Evaluate*: Evaluate mathematical expressions and store result in property. - - *SetPropertyFromPipe*: Allows setting property from a pipe. - - *SqlSearch*: Execute a SQL query and place result in a property. - - *ReadIniValues*: Reads .INI file values. - - *XmlSearch*: Read XML values. - - *RegularExpression*: Execute a Regular Expression to replace or find matches in property values and in file contents. - - *MsiSqlQuery*: Execute a MSI-SQL query on the MSI database. - - *CreateSelfSignCertificate*: Create a self-sign certificate that can then be installed by WixIisExtension. - - *ToLowerCase*: Convert property value to lowercase. - - *CustomPatchRef* Support referencing custom table rows in a patch - - *Payload* Support extracting files from Binary table temporarilty during MSI execution - - *PromptFileDowngrades* Log each file that will be downgraded during the (re)install, and prompt the total downgrade count if larger than 0. -- Deferred Actions: - - *ExecuteCommand*: Launch a deferred command - - *RestartLocalResources*: Register processes with the Restart Manager if they reside in the specified folder - - *XslTransform*: Apply a XSL transform on an installed XML file - - *WebsiteConfig*: currently, can only stop a website - - *JsonJPath*: Set values in JSON-formatted file. - - *Dism*: Enable or disable Windows Features using DISM API. Features will be modified when the parent component is being installed or repaired. - - *ZipFile*: Creates a ZIP archive from selected files. - - *Unzip*: Extract a ZIP archive to selected folder. - - *CustomUninstallKey*: Overwrite registry values in the product's [Uninstall](http://msdn.microsoft.com/en-us/library/aa372105%28v=vs.85%29.aspx) registry key - - *RemoveRegistryValue*: Removes registry values. Complements the standard [RemoveRegistryValue](http://wixtoolset.org/documentation/manual/v3/xsd/wix/removeregistryvalue.html) WiX element that will only remove registry values during installation. - - *ExecOn*: Execute a custom command on component action. - - *TaskScheduler*: Add a task to Windows Task Scheduler. - - *DeletePath*: Delete folder or file specified by a path. - - *FileRegex*: Execute a Regular Expression to perform find & replace operations within files. - - *ShellExecute*: Call ShellExecuteEx with parameters. - - *Telemetry*: Send telemetry data to a given URL. - - *InstallUtil*: Install a .NET assembly service. - - *TopShelf*: Install a [TopShelf](http://topshelf-project.com/) based service. - - *BackupAndRestore*: Backup a file before install or upgarde and restore it after. - - *SqlScript*: Execute SQL scripts, optionally with text replacements. - - *SplitFile*: Splits a file to parts during build, and reconstruct it during install. Used to workaround MSI limitation of 2GB file size. - -## Preprocessor -- *$(psw.VarNullOrEmpty(VAR_NAME))*: Return 1 if the variable is not defined, or if it defined as empty. Return 0 otherwise -- *$(psw.AutoGuid(x,y,z,...))*: Return a pseudo-random UUID per arguments -- *$(psw.FileExists(path))*: Return 1 if the file exists, 0 otherwise -- *$(psw.DirExists(path))*: Return 1 if the folder exists, 0 otherwise -- *$(psw.DirEmpty(path))*: Return 1 if the folder doesn't exist or if it has no files (including in subfolders). Return 0 otherwise - -## Custom Actions - -- *TerminateSuccessfully_Immediate*: Terminates the installation with a successful indication. Executed in-script. -- *TerminateSuccessfully_Deferred*: Terminates the installation with a successful indication. Deferred execution. -- *SplitPath*: Split a full path supplied in 'FULL_PATH_TO_SPLIT' property and places the parts in properties SPLIT_DRIVE, SPLIT_FOLDER, SPLIT_FILE_NAME, SPLIT_FILE_EXTENSION. -- *PathExists*: Tests whether the path supplied in 'FULL_PATH_TO_TEST' property exists. Sets 'PATH_EXISTS' property to 1 if it exists or clears it if it doesn't. -- *SplitString*: Splits a string. Property name specified in 'PROPERTY_TO_SPLIT' and split token specified in 'STRING_SPLIT_TOKEN'. Results are stored in properties following the name supplied in 'PROPERTY_TO_SPLIT'. - For example, say PROPERTY_TO_SPLIT="MY_PROP", MY_PROP="1,2,3" and STRING_SPLIT_TOKEN=",". Scheduling SplitString custom action will yield properties MY_PROP_0="1", MY_PROP_1="2" and MY_PROP_2="3". -- *TrimString*: Trim whitespace characters in property with name specified in 'PROPERTY_TO_TRIM'. - -## Error codes - -PanelSwWixExtension uses error codes in Error table: - -- 27000: TopShelf error template for prompting user on errors. -- 27001: ExecOn error template for prompting user on errors. -- 27002: ServiceConfig error template for prompting user on errors. -- 27003: Dism error template for prompting user on failures to add a Windows feature package. -- 27004: Dism error template for prompting user on failures to enable a Windows feature. -- 27005: SqlScript error template for prompting user on errors. -- 27006: ExecOn error template for prompting user on console output parsing. -- 27007: WebsiteConfig error template for prompting user on errors. -- 27008: SqlSearch error template for prompting user on errors. -- 27009: JsonJpath error template for prompting user on errors. -- 27010: Dism error template for prompting user on failures to remove a Windows feature package. -- 27011: ExecOn message template for prompting user on success with promptAlways. -- 27012: Prompt on file downgrades -- 27013: Prompt on failure to add a file to a ZIP archive -- 27014: Prompt on failure to create a ZIP archive -- 27015: Prompt on failure to unzip a ZIP archive -- 27016: Prompt on failure to unzip a file from ZIP archive - -## Properties - -The following properties hold localized built-in account names. To use them, add a [PropertyRef](http://wixtoolset.org/documentation/manual/v3/xsd/wix/propertyref.html) element. - -- DOMAIN_ADMINISTRATORS -- DOMAIN_GUESTS -- DOMAIN_USERS -- ENTERPRISE_DOMAIN_CONTROLLERS -- DOMAIN_DOMAIN_CONTROLLERS -- DOMAIN_COMPUTERS -- BUILTIN_ADMINISTRATORS -- BUILTIN_GUESTS -- BUILTIN_USERS -- LOCAL_ADMIN -- LOCAL_GUEST -- ACCOUNT_OPERATORS -- BACKUP_OPERATORS -- PRINTER_OPERATORS -- SERVER_OPERATORS -- AUTHENTICATED_USERS -- PERSONAL_SELF -- CREATOR_OWNER -- CREATOR_GROUP -- LOCAL_SYSTEM -- POWER_USERS -- EVERYONE -- REPLICATOR -- INTERACTIVE -- NETWORK -- SERVICE -- RESTRICTED_CODE -- WRITE_RESTRICTED_CODE -- ANONYMOUS -- SCHEMA_ADMINISTRATORS -- CERT_SERV_ADMINISTRATORS -- RAS_SERVERS -- ENTERPRISE_ADMINS -- GROUP_POLICY_ADMINS -- ALIAS_PREW2KCOMPACC -- LOCAL_SERVICE -- NETWORK_SERVICE -- REMOTE_DESKTOP -- NETWORK_CONFIGURATION_OPS -- PERFMON_USERS -- PERFLOG_USERS -- IIS_USERS -- CRYPTO_OPERATORS -- OWNER_RIGHTS -- EVENT_LOG_READERS -- ENTERPRISE_RO_DCs -- CERTSVC_DCOM_ACCESS - -The following properties hold localized CSIDL folders. To use them, add a [PropertyRef](http://wixtoolset.org/documentation/manual/v3/xsd/wix/propertyref.html) element. - -- UserDesktopFolder: CSIDL_DESKTOPDIRECTORY - -The following [properties](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent) denote available processor features. 1 means that the feature is available, 0 means that it is not available. - -- PF_ARM_64BIT_LOADSTORE_ATOMIC -- PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE -- PF_ARM_EXTERNAL_CACHE_AVAILABLE -- PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE -- PF_ARM_VFP_32_REGISTERS_AVAILABLE -- PF_3DNOW_INSTRUCTIONS_AVAILABLE -- PF_CHANNELS_ENABLED -- PF_COMPARE_EXCHANGE_DOUBLE -- PF_COMPARE_EXCHANGE128 -- PF_COMPARE64_EXCHANGE128 -- PF_FASTFAIL_AVAILABLE -- PF_FLOATING_POINT_EMULATED -- PF_FLOATING_POINT_PRECISION_ERRATA -- PF_MMX_INSTRUCTIONS_AVAILABLE -- PF_NX_ENABLED -- PF_PAE_ENABLED -- PF_RDTSC_INSTRUCTION_AVAILABLE -- PF_RDWRFSGSBASE_AVAILABLE -- PF_SECOND_LEVEL_ADDRESS_TRANSLATION -- PF_SSE3_INSTRUCTIONS_AVAILABLE -- PF_SSSE3_INSTRUCTIONS_AVAILABLE -- PF_SSE4_1_INSTRUCTIONS_AVAILABLE -- PF_SSE4_2_INSTRUCTIONS_AVAILABLE -- PF_AVX_INSTRUCTIONS_AVAILABLE -- PF_AVX2_INSTRUCTIONS_AVAILABLE -- PF_AVX512F_INSTRUCTIONS_AVAILABLE -- PF_VIRT_FIRMWARE_ENABLED -- PF_XMMI_INSTRUCTIONS_AVAILABLE -- PF_XMMI64_INSTRUCTIONS_AVAILABLE -- PF_XSAVE_ENABLED -- PF_ARM_V8_INSTRUCTIONS_AVAILABLE -- PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE -- PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE -- PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE -- PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE -- PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE -- PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE - -## Building - -PanelSwWixExtension require the following prerequisites to build: -- CMake: CMake path can be specified in 'CMakeDir' property in 'TidyBuild.custom.props' -- ADK installed. Specifically, Dism API should be installed. Set DismApi folder path in 'DismApiDir' property in 'TidyBuild.custom.props' -- Update git submodules - -To build the extension execute: -~~~ -msbuild dirs.proj -restore "-p:SolutionDir=%CD%\" -~~~ - -Unit-test WiX are available in the solution folder 'UnitTests'. -To build a unit test project execute: -~~~~~~~~~~~~ -msbuild dirs.proj -restore -p:UnitTest=ForceVersionUT -~~~~~~~~~~~~ +[![PanelSwWixExtension](https://github.com/nirbar/PanelSwWixExtension/actions/workflows/github-actions-build.yml/badge.svg?branch=master4)](https://github.com/nirbar/PanelSwWixExtension/actions/workflows/github-actions-build.yml) +WiX v3 [![NuGet version (PanelSwWixExtension)](https://img.shields.io/nuget/v/PanelSwWixExtension.svg?style=flat-square)](https://www.nuget.org/packages/PanelSwWixExtension/) +WiX v4 [![NuGet version (PanelSwWixExtension4)](https://img.shields.io/nuget/v/PanelSwWixExtension4.svg?style=flat-square)](https://www.nuget.org/packages/PanelSwWixExtension4/) + +PanelSwWixExtension from the creator of [JetBA](https://github.com/nirbar/JetBA-Binaries) is the most comprehensive open source [WiX](http://wixtoolset.org/) extension. +I would like to thank JetBrains for their [support](https://www.jetbrains.com/community/opensource/) of this project + +## PanelSwWixExtension WiX Elements + +- Bundle elements: + - *ContainerTemplate*: A container template to which bundle payloads can be assigned + - Wיhen using PanelSwWix4.Sdk, support 7z and Zip containers + - *!(bindpath.PanelSwWixExtension)\x86\DeferredExePackage.exe* An executable that can execute arbitrary commands during chain execution + - Use InstallArguments='--skip-until-here "[SomeExecutable]" "arg1" "arg2"': Create a process with any arguments after the `--skip-until-here` part + - Use InstallArguments='--ignore-me': Ignore anything after the `--ignore-me` part +- Heat extension command line arguments: + - *-inc*: Semicolon seperated list of filename to include. Wildcards are accepted. If specified, any file not matching the pattern will be excluded + - *-exc*: Semicolon seperated list of filename to exclude. Wildcards are accepted. If specified, any file matching the pattern will be excluded + - *-prd*: Payload Root Folder. A prefix folder to add to all payloads +- Immediate Actions: + - *DuplicateFolder*: Duplicate an entire folder hierarchy. Processed at build time by adding entries to Directory, CreateFolder and DuplicateFile tables. + - *IsWindowsVersionOrGreater*: Test whether Kernel32.dll's version is at least the given version. If yes, set the property to 1. + - *Md5Hash*: Computes MD5 hash. + - *WmiSearch*: Execute a WMI query. + - *PathSearch*: Search for a file on PATH environment variable folder list. + - *VersionCompare*: Compare two versions, set result to property to value in range -4 to +4, denoting the version part that was different (-+4 if Major part was different, -+3 for Minor part, etc.) + - *ForceVersion*: Force a specified version for a file. Version overwrite is done on runtime in the MSI database. + - *AccountSidSearch*: Lookup an account's SID by account name. + - *JsonJpathSearch*: Read JSON values + - *DiskSpace*: Calculate available disk space for a target directory + - *CertificateHashSearch*: Find a certificate hash in local system MY store. + - *Evaluate*: Evaluate mathematical expressions and store result in property. + - *SetPropertyFromPipe*: Allows setting property from a pipe. + - *SqlSearch*: Execute a SQL query and place result in a property. + - *ReadIniValues*: Reads .INI file values. + - *XmlSearch*: Read XML values. + - *RegularExpression*: Execute a Regular Expression to replace or find matches in property values and in file contents. + - *MsiSqlQuery*: Execute a MSI-SQL query on the MSI database. + - *CreateSelfSignCertificate*: Create a self-sign certificate that can then be installed by WixIisExtension. + - *ToLowerCase*: Convert property value to lowercase. + - *CustomPatchRef* Support referencing custom table rows in a patch + - *Payload* Support extracting files from Binary table temporarilty during MSI execution + - *PromptFileDowngrades* Log each file that will be downgraded during the (re)install, and prompt the total downgrade count if larger than 0. +- Deferred Actions: + - *ExecuteCommand*: Launch a deferred command + - *RestartLocalResources*: Register processes with the Restart Manager if they reside in the specified folder + - *XslTransform*: Apply a XSL transform on an installed XML file + - *WebsiteConfig*: currently, can only stop a website + - *JsonJPath*: Set values in JSON-formatted file. + - *Dism*: Enable or disable Windows Features using DISM API. Features will be modified when the parent component is being installed or repaired. + - *ZipFile*: Creates a ZIP archive from selected files. + - *Unzip*: Extract a ZIP archive to selected folder. + - *CustomUninstallKey*: Overwrite registry values in the product's [Uninstall](http://msdn.microsoft.com/en-us/library/aa372105%28v=vs.85%29.aspx) registry key + - *RemoveRegistryValue*: Removes registry values. Complements the standard [RemoveRegistryValue](http://wixtoolset.org/documentation/manual/v3/xsd/wix/removeregistryvalue.html) WiX element that will only remove registry values during installation. + - *ExecOn*: Execute a custom command on component action. + - *TaskScheduler*: Add a task to Windows Task Scheduler. + - *DeletePath*: Delete folder or file specified by a path. + - *FileRegex*: Execute a Regular Expression to perform find & replace operations within files. + - *ShellExecute*: Call ShellExecuteEx with parameters. + - *Telemetry*: Send telemetry data to a given URL. + - *InstallUtil*: Install a .NET assembly service. + - *TopShelf*: Install a [TopShelf](http://topshelf-project.com/) based service. + - *BackupAndRestore*: Backup a file before install or upgarde and restore it after. + - *SqlScript*: Execute SQL scripts, optionally with text replacements. + - *SplitFile*: Splits a file to parts during build, and reconstruct it during install. Used to workaround MSI limitation of 2GB file size. + +## Preprocessor +- *$(psw.VarNullOrEmpty(VAR_NAME))*: Return 1 if the variable is not defined, or if it defined as empty. Return 0 otherwise +- *$(psw.AutoGuid(x,y,z,...))*: Return a pseudo-random UUID per arguments +- *$(psw.FileExists(path))*: Return 1 if the file exists, 0 otherwise +- *$(psw.DirExists(path))*: Return 1 if the folder exists, 0 otherwise +- *$(psw.DirEmpty(path))*: Return 1 if the folder doesn't exist or if it has no files (including in subfolders). Return 0 otherwise + +## Custom Actions + +- *TerminateSuccessfully_Immediate*: Terminates the installation with a successful indication. Executed in-script. +- *TerminateSuccessfully_Deferred*: Terminates the installation with a successful indication. Deferred execution. +- *SplitPath*: Split a full path supplied in 'FULL_PATH_TO_SPLIT' property and places the parts in properties SPLIT_DRIVE, SPLIT_FOLDER, SPLIT_FILE_NAME, SPLIT_FILE_EXTENSION. +- *PathExists*: Tests whether the path supplied in 'FULL_PATH_TO_TEST' property exists. Sets 'PATH_EXISTS' property to 1 if it exists or clears it if it doesn't. +- *SplitString*: Splits a string. Property name specified in 'PROPERTY_TO_SPLIT' and split token specified in 'STRING_SPLIT_TOKEN'. Results are stored in properties following the name supplied in 'PROPERTY_TO_SPLIT'. + For example, say PROPERTY_TO_SPLIT="MY_PROP", MY_PROP="1,2,3" and STRING_SPLIT_TOKEN=",". Scheduling SplitString custom action will yield properties MY_PROP_0="1", MY_PROP_1="2" and MY_PROP_2="3". +- *TrimString*: Trim whitespace characters in property with name specified in 'PROPERTY_TO_TRIM'. + +## Error codes + +PanelSwWixExtension uses error codes in Error table: + +- 27000: TopShelf error template for prompting user on errors. +- 27001: ExecOn error template for prompting user on errors. +- 27002: ServiceConfig error template for prompting user on errors. +- 27003: Dism error template for prompting user on failures to add a Windows feature package. +- 27004: Dism error template for prompting user on failures to enable a Windows feature. +- 27005: SqlScript error template for prompting user on errors. +- 27006: ExecOn error template for prompting user on console output parsing. +- 27007: WebsiteConfig error template for prompting user on errors. +- 27008: SqlSearch error template for prompting user on errors. +- 27009: JsonJpath error template for prompting user on errors. +- 27010: Dism error template for prompting user on failures to remove a Windows feature package. +- 27011: ExecOn message template for prompting user on success with promptAlways. +- 27012: Prompt on file downgrades +- 27013: Prompt on failure to add a file to a ZIP archive +- 27014: Prompt on failure to create a ZIP archive +- 27015: Prompt on failure to unzip a ZIP archive +- 27016: Prompt on failure to unzip a file from ZIP archive + +## Properties + +The following properties hold localized built-in account names. To use them, add a [PropertyRef](http://wixtoolset.org/documentation/manual/v3/xsd/wix/propertyref.html) element. + +- DOMAIN_ADMINISTRATORS +- DOMAIN_GUESTS +- DOMAIN_USERS +- ENTERPRISE_DOMAIN_CONTROLLERS +- DOMAIN_DOMAIN_CONTROLLERS +- DOMAIN_COMPUTERS +- BUILTIN_ADMINISTRATORS +- BUILTIN_GUESTS +- BUILTIN_USERS +- LOCAL_ADMIN +- LOCAL_GUEST +- ACCOUNT_OPERATORS +- BACKUP_OPERATORS +- PRINTER_OPERATORS +- SERVER_OPERATORS +- AUTHENTICATED_USERS +- PERSONAL_SELF +- CREATOR_OWNER +- CREATOR_GROUP +- LOCAL_SYSTEM +- POWER_USERS +- EVERYONE +- REPLICATOR +- INTERACTIVE +- NETWORK +- SERVICE +- RESTRICTED_CODE +- WRITE_RESTRICTED_CODE +- ANONYMOUS +- SCHEMA_ADMINISTRATORS +- CERT_SERV_ADMINISTRATORS +- RAS_SERVERS +- ENTERPRISE_ADMINS +- GROUP_POLICY_ADMINS +- ALIAS_PREW2KCOMPACC +- LOCAL_SERVICE +- NETWORK_SERVICE +- REMOTE_DESKTOP +- NETWORK_CONFIGURATION_OPS +- PERFMON_USERS +- PERFLOG_USERS +- IIS_USERS +- CRYPTO_OPERATORS +- OWNER_RIGHTS +- EVENT_LOG_READERS +- ENTERPRISE_RO_DCs +- CERTSVC_DCOM_ACCESS + +The following properties hold localized CSIDL folders. To use them, add a [PropertyRef](http://wixtoolset.org/documentation/manual/v3/xsd/wix/propertyref.html) element. + +- UserDesktopFolder: CSIDL_DESKTOPDIRECTORY + +The following [properties](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent) denote available processor features. 1 means that the feature is available, 0 means that it is not available. + +- PF_ARM_64BIT_LOADSTORE_ATOMIC +- PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE +- PF_ARM_EXTERNAL_CACHE_AVAILABLE +- PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE +- PF_ARM_VFP_32_REGISTERS_AVAILABLE +- PF_3DNOW_INSTRUCTIONS_AVAILABLE +- PF_CHANNELS_ENABLED +- PF_COMPARE_EXCHANGE_DOUBLE +- PF_COMPARE_EXCHANGE128 +- PF_COMPARE64_EXCHANGE128 +- PF_FASTFAIL_AVAILABLE +- PF_FLOATING_POINT_EMULATED +- PF_FLOATING_POINT_PRECISION_ERRATA +- PF_MMX_INSTRUCTIONS_AVAILABLE +- PF_NX_ENABLED +- PF_PAE_ENABLED +- PF_RDTSC_INSTRUCTION_AVAILABLE +- PF_RDWRFSGSBASE_AVAILABLE +- PF_SECOND_LEVEL_ADDRESS_TRANSLATION +- PF_SSE3_INSTRUCTIONS_AVAILABLE +- PF_SSSE3_INSTRUCTIONS_AVAILABLE +- PF_SSE4_1_INSTRUCTIONS_AVAILABLE +- PF_SSE4_2_INSTRUCTIONS_AVAILABLE +- PF_AVX_INSTRUCTIONS_AVAILABLE +- PF_AVX2_INSTRUCTIONS_AVAILABLE +- PF_AVX512F_INSTRUCTIONS_AVAILABLE +- PF_VIRT_FIRMWARE_ENABLED +- PF_XMMI_INSTRUCTIONS_AVAILABLE +- PF_XMMI64_INSTRUCTIONS_AVAILABLE +- PF_XSAVE_ENABLED +- PF_ARM_V8_INSTRUCTIONS_AVAILABLE +- PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE +- PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE +- PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE +- PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE +- PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE +- PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE + +## Building + +PanelSwWixExtension require the following prerequisites to build: +- CMake: CMake path can be specified in 'CMakeDir' property in 'TidyBuild.custom.props' +- ADK installed. Specifically, Dism API should be installed. Set DismApi folder path in 'DismApiDir' property in 'TidyBuild.custom.props' +- Update git submodules + +To build the extension execute: +~~~ +msbuild dirs.proj -restore "-p:SolutionDir=%CD%\" +~~~ + +Unit-test WiX are available in the solution folder 'UnitTests'. +To build a unit test project execute: +~~~~~~~~~~~~ +msbuild dirs.proj -restore -p:UnitTest=ForceVersionUT +~~~~~~~~~~~~ diff --git a/TidyBuild.custom.props b/src/TidyBuild.custom.props similarity index 97% rename from TidyBuild.custom.props rename to src/TidyBuild.custom.props index 2fbca694..76c35611 100644 --- a/TidyBuild.custom.props +++ b/src/TidyBuild.custom.props @@ -2,14 +2,13 @@ - 3.16.1 + 3.17.0 $(FullVersion).$(GITHUB_RUN_NUMBER) PanelSwWixExtension Panel::Software - + true @@ -36,7 +35,7 @@ - $(MSBuildThisFileDirectory)build\ + $(MSBuildThisFileDirectory)..\build\ $(BaseBuildFolder)obj\$(MSBuildProjectName)\ $(BaseIntermediateOutputPath) diff --git a/TidyBuild.custom.targets b/src/TidyBuild.custom.targets similarity index 100% rename from TidyBuild.custom.targets rename to src/TidyBuild.custom.targets diff --git a/UnitTests/AccountNamesUT/AccountNamesUT.wixproj b/src/UnitTests/AccountNamesUT/AccountNamesUT.wixproj similarity index 100% rename from UnitTests/AccountNamesUT/AccountNamesUT.wixproj rename to src/UnitTests/AccountNamesUT/AccountNamesUT.wixproj diff --git a/UnitTests/AccountNamesUT/AccountNamesUT.wxs b/src/UnitTests/AccountNamesUT/AccountNamesUT.wxs similarity index 100% rename from UnitTests/AccountNamesUT/AccountNamesUT.wxs rename to src/UnitTests/AccountNamesUT/AccountNamesUT.wxs diff --git a/UnitTests/AccountSidSearchUT/AccountSidSearchUT.wixproj b/src/UnitTests/AccountSidSearchUT/AccountSidSearchUT.wixproj similarity index 100% rename from UnitTests/AccountSidSearchUT/AccountSidSearchUT.wixproj rename to src/UnitTests/AccountSidSearchUT/AccountSidSearchUT.wixproj diff --git a/UnitTests/AccountSidSearchUT/AccountSidSearchUT.wxs b/src/UnitTests/AccountSidSearchUT/AccountSidSearchUT.wxs similarity index 100% rename from UnitTests/AccountSidSearchUT/AccountSidSearchUT.wxs rename to src/UnitTests/AccountSidSearchUT/AccountSidSearchUT.wxs diff --git a/UnitTests/BackupAndRestoreUT/BackupAndRestoreUT.wixproj b/src/UnitTests/BackupAndRestoreUT/BackupAndRestoreUT.wixproj similarity index 97% rename from UnitTests/BackupAndRestoreUT/BackupAndRestoreUT.wixproj rename to src/UnitTests/BackupAndRestoreUT/BackupAndRestoreUT.wixproj index c1f3bd67..6ee14fd0 100644 --- a/UnitTests/BackupAndRestoreUT/BackupAndRestoreUT.wixproj +++ b/src/UnitTests/BackupAndRestoreUT/BackupAndRestoreUT.wixproj @@ -1,21 +1,21 @@ - - - false - - - Release - 3.8 - BackupAndRestoreUT - - - - - - - $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll - PanelSwWixExtension - - - - + + + false + + + Release + 3.8 + BackupAndRestoreUT + + + + + + + $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll + PanelSwWixExtension + + + + \ No newline at end of file diff --git a/UnitTests/BackupAndRestoreUT/BackupAndRestoreUT.wxs b/src/UnitTests/BackupAndRestoreUT/BackupAndRestoreUT.wxs similarity index 100% rename from UnitTests/BackupAndRestoreUT/BackupAndRestoreUT.wxs rename to src/UnitTests/BackupAndRestoreUT/BackupAndRestoreUT.wxs diff --git a/UnitTests/CleanPendingFileRenameOperationsUT/CleanPendingFileRenameOperationsUT.wixproj b/src/UnitTests/CleanPendingFileRenameOperationsUT/CleanPendingFileRenameOperationsUT.wixproj similarity index 100% rename from UnitTests/CleanPendingFileRenameOperationsUT/CleanPendingFileRenameOperationsUT.wixproj rename to src/UnitTests/CleanPendingFileRenameOperationsUT/CleanPendingFileRenameOperationsUT.wixproj diff --git a/UnitTests/CleanPendingFileRenameOperationsUT/CleanPendingFileRenameOperationsUT.wxs b/src/UnitTests/CleanPendingFileRenameOperationsUT/CleanPendingFileRenameOperationsUT.wxs similarity index 100% rename from UnitTests/CleanPendingFileRenameOperationsUT/CleanPendingFileRenameOperationsUT.wxs rename to src/UnitTests/CleanPendingFileRenameOperationsUT/CleanPendingFileRenameOperationsUT.wxs diff --git a/UnitTests/ContainerTemplateUT/ContainerTemplateUT.wixproj b/src/UnitTests/ContainerTemplateUT/ContainerTemplateUT.wixproj similarity index 81% rename from UnitTests/ContainerTemplateUT/ContainerTemplateUT.wixproj rename to src/UnitTests/ContainerTemplateUT/ContainerTemplateUT.wixproj index a7c65e64..4261d0de 100644 --- a/UnitTests/ContainerTemplateUT/ContainerTemplateUT.wixproj +++ b/src/UnitTests/ContainerTemplateUT/ContainerTemplateUT.wixproj @@ -22,7 +22,8 @@ -generate payloadgroup - $(DefineConstants);THISDIR=$(MSBuildThisFileDirectory)..\ + $(BuildFolder)bin\Release\DeferredExePackage\DeferredExePackage.exe + $(DefineConstants);DeferredExePackagePath=$(DeferredExePackagePath);EnableZipContainer=$(EnableZipContainer);THISDIR=$(MSBuildThisFileDirectory)..\ diff --git a/UnitTests/ContainerTemplateUT/ContainerTemplateUT.wxs b/src/UnitTests/ContainerTemplateUT/ContainerTemplateUT.wxs similarity index 67% rename from UnitTests/ContainerTemplateUT/ContainerTemplateUT.wxs rename to src/UnitTests/ContainerTemplateUT/ContainerTemplateUT.wxs index 8bfc1826..aede06c9 100644 --- a/UnitTests/ContainerTemplateUT/ContainerTemplateUT.wxs +++ b/src/UnitTests/ContainerTemplateUT/ContainerTemplateUT.wxs @@ -3,10 +3,14 @@ - + + + + + - + diff --git a/UnitTests/CreateSelfSignCertificateUT/CreateSelfSignCertificateUT.wixproj b/src/UnitTests/CreateSelfSignCertificateUT/CreateSelfSignCertificateUT.wixproj similarity index 100% rename from UnitTests/CreateSelfSignCertificateUT/CreateSelfSignCertificateUT.wixproj rename to src/UnitTests/CreateSelfSignCertificateUT/CreateSelfSignCertificateUT.wixproj diff --git a/UnitTests/CreateSelfSignCertificateUT/CreateSelfSignCertificateUT.wxs b/src/UnitTests/CreateSelfSignCertificateUT/CreateSelfSignCertificateUT.wxs similarity index 100% rename from UnitTests/CreateSelfSignCertificateUT/CreateSelfSignCertificateUT.wxs rename to src/UnitTests/CreateSelfSignCertificateUT/CreateSelfSignCertificateUT.wxs diff --git a/UnitTests/CustomActionDataUT/CustomActionDataUT.wixproj b/src/UnitTests/CustomActionDataUT/CustomActionDataUT.wixproj similarity index 100% rename from UnitTests/CustomActionDataUT/CustomActionDataUT.wixproj rename to src/UnitTests/CustomActionDataUT/CustomActionDataUT.wixproj diff --git a/UnitTests/CustomActionDataUT/CustomActionDataUT.wxs b/src/UnitTests/CustomActionDataUT/CustomActionDataUT.wxs similarity index 100% rename from UnitTests/CustomActionDataUT/CustomActionDataUT.wxs rename to src/UnitTests/CustomActionDataUT/CustomActionDataUT.wxs diff --git a/UnitTests/CustomUninstallKeyUT/CustomUninstallKeyUT.wixproj b/src/UnitTests/CustomUninstallKeyUT/CustomUninstallKeyUT.wixproj old mode 100755 new mode 100644 similarity index 97% rename from UnitTests/CustomUninstallKeyUT/CustomUninstallKeyUT.wixproj rename to src/UnitTests/CustomUninstallKeyUT/CustomUninstallKeyUT.wixproj index 539fe387..67fe35e0 --- a/UnitTests/CustomUninstallKeyUT/CustomUninstallKeyUT.wixproj +++ b/src/UnitTests/CustomUninstallKeyUT/CustomUninstallKeyUT.wixproj @@ -1,21 +1,21 @@ - - - false - - - Release - 3.8 - - - - - - - $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll - PanelSwWixExtension - - - - - + + + false + + + Release + 3.8 + + + + + + + $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll + PanelSwWixExtension + + + + + \ No newline at end of file diff --git a/UnitTests/CustomUninstallKeyUT/CustomUninstallKeyUT.wxs b/src/UnitTests/CustomUninstallKeyUT/CustomUninstallKeyUT.wxs similarity index 100% rename from UnitTests/CustomUninstallKeyUT/CustomUninstallKeyUT.wxs rename to src/UnitTests/CustomUninstallKeyUT/CustomUninstallKeyUT.wxs diff --git a/UnitTests/DiskSpaceUT/DiskSpaceUT.wixproj b/src/UnitTests/DiskSpaceUT/DiskSpaceUT.wixproj similarity index 100% rename from UnitTests/DiskSpaceUT/DiskSpaceUT.wixproj rename to src/UnitTests/DiskSpaceUT/DiskSpaceUT.wixproj diff --git a/UnitTests/DiskSpaceUT/DiskSpaceUT.wxs b/src/UnitTests/DiskSpaceUT/DiskSpaceUT.wxs similarity index 100% rename from UnitTests/DiskSpaceUT/DiskSpaceUT.wxs rename to src/UnitTests/DiskSpaceUT/DiskSpaceUT.wxs diff --git a/UnitTests/DismUT/DismUT.wixproj b/src/UnitTests/DismUT/DismUT.wixproj similarity index 97% rename from UnitTests/DismUT/DismUT.wixproj rename to src/UnitTests/DismUT/DismUT.wixproj index f48869e7..c683e9b7 100644 --- a/UnitTests/DismUT/DismUT.wixproj +++ b/src/UnitTests/DismUT/DismUT.wixproj @@ -1,21 +1,21 @@ - - - false - - - Release - 3.8 - $(MSBuildProjectName) - - - - - - - - - $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll - PanelSwWixExtension - - + + + false + + + Release + 3.8 + $(MSBuildProjectName) + + + + + + + + + $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll + PanelSwWixExtension + + \ No newline at end of file diff --git a/UnitTests/DismUT/DismUT.wxs b/src/UnitTests/DismUT/DismUT.wxs similarity index 100% rename from UnitTests/DismUT/DismUT.wxs rename to src/UnitTests/DismUT/DismUT.wxs diff --git a/UnitTests/DuplicateFolderUT/DuplicateFolderUT.wixproj b/src/UnitTests/DuplicateFolderUT/DuplicateFolderUT.wixproj similarity index 100% rename from UnitTests/DuplicateFolderUT/DuplicateFolderUT.wixproj rename to src/UnitTests/DuplicateFolderUT/DuplicateFolderUT.wixproj diff --git a/UnitTests/DuplicateFolderUT/DuplicateFolderUT.wxs b/src/UnitTests/DuplicateFolderUT/DuplicateFolderUT.wxs similarity index 100% rename from UnitTests/DuplicateFolderUT/DuplicateFolderUT.wxs rename to src/UnitTests/DuplicateFolderUT/DuplicateFolderUT.wxs diff --git a/UnitTests/EvaluateExpressionUT/EvaluateExpressionUT.wixproj b/src/UnitTests/EvaluateExpressionUT/EvaluateExpressionUT.wixproj similarity index 100% rename from UnitTests/EvaluateExpressionUT/EvaluateExpressionUT.wixproj rename to src/UnitTests/EvaluateExpressionUT/EvaluateExpressionUT.wixproj diff --git a/UnitTests/EvaluateExpressionUT/EvaluateExpressionUT.wxs b/src/UnitTests/EvaluateExpressionUT/EvaluateExpressionUT.wxs similarity index 100% rename from UnitTests/EvaluateExpressionUT/EvaluateExpressionUT.wxs rename to src/UnitTests/EvaluateExpressionUT/EvaluateExpressionUT.wxs diff --git a/UnitTests/ExecOnComponentUT/ExecOnComponentUT.wixproj b/src/UnitTests/ExecOnComponentUT/ExecOnComponentUT.wixproj similarity index 100% rename from UnitTests/ExecOnComponentUT/ExecOnComponentUT.wixproj rename to src/UnitTests/ExecOnComponentUT/ExecOnComponentUT.wixproj diff --git a/UnitTests/ExecOnComponentUT/ExecOnComponentUT.wxs b/src/UnitTests/ExecOnComponentUT/ExecOnComponentUT.wxs similarity index 100% rename from UnitTests/ExecOnComponentUT/ExecOnComponentUT.wxs rename to src/UnitTests/ExecOnComponentUT/ExecOnComponentUT.wxs diff --git a/UnitTests/ExecOnComponentUT/non-printable.txt b/src/UnitTests/ExecOnComponentUT/non-printable.txt similarity index 100% rename from UnitTests/ExecOnComponentUT/non-printable.txt rename to src/UnitTests/ExecOnComponentUT/non-printable.txt diff --git a/UnitTests/ExecuteCommandUT/ExecuteCommandUT.wixproj b/src/UnitTests/ExecuteCommandUT/ExecuteCommandUT.wixproj similarity index 100% rename from UnitTests/ExecuteCommandUT/ExecuteCommandUT.wixproj rename to src/UnitTests/ExecuteCommandUT/ExecuteCommandUT.wixproj diff --git a/UnitTests/ExecuteCommandUT/ExecuteCommandUT.wxs b/src/UnitTests/ExecuteCommandUT/ExecuteCommandUT.wxs similarity index 100% rename from UnitTests/ExecuteCommandUT/ExecuteCommandUT.wxs rename to src/UnitTests/ExecuteCommandUT/ExecuteCommandUT.wxs diff --git a/UnitTests/FileOperationsUT/FileOperationsUT.wixproj b/src/UnitTests/FileOperationsUT/FileOperationsUT.wixproj similarity index 100% rename from UnitTests/FileOperationsUT/FileOperationsUT.wixproj rename to src/UnitTests/FileOperationsUT/FileOperationsUT.wixproj diff --git a/UnitTests/FileOperationsUT/FileOperationsUT.wxs b/src/UnitTests/FileOperationsUT/FileOperationsUT.wxs similarity index 100% rename from UnitTests/FileOperationsUT/FileOperationsUT.wxs rename to src/UnitTests/FileOperationsUT/FileOperationsUT.wxs diff --git a/UnitTests/ForceVersionUT/ForceVersionUT.wixproj b/src/UnitTests/ForceVersionUT/ForceVersionUT.wixproj similarity index 100% rename from UnitTests/ForceVersionUT/ForceVersionUT.wixproj rename to src/UnitTests/ForceVersionUT/ForceVersionUT.wixproj diff --git a/UnitTests/ForceVersionUT/ForceVersionUT.wxs b/src/UnitTests/ForceVersionUT/ForceVersionUT.wxs similarity index 100% rename from UnitTests/ForceVersionUT/ForceVersionUT.wxs rename to src/UnitTests/ForceVersionUT/ForceVersionUT.wxs diff --git a/UnitTests/HeatExtUT/HeatExtUT.wixproj b/src/UnitTests/HeatExtUT/HeatExtUT.wixproj similarity index 100% rename from UnitTests/HeatExtUT/HeatExtUT.wixproj rename to src/UnitTests/HeatExtUT/HeatExtUT.wixproj diff --git a/UnitTests/HeatExtUT/HeatExtUT.wxs b/src/UnitTests/HeatExtUT/HeatExtUT.wxs similarity index 100% rename from UnitTests/HeatExtUT/HeatExtUT.wxs rename to src/UnitTests/HeatExtUT/HeatExtUT.wxs diff --git a/UnitTests/InstallUtilUT/InstallUtilUT.wixproj b/src/UnitTests/InstallUtilUT/InstallUtilUT.wixproj similarity index 97% rename from UnitTests/InstallUtilUT/InstallUtilUT.wixproj rename to src/UnitTests/InstallUtilUT/InstallUtilUT.wixproj index c358df8b..da34a548 100644 --- a/UnitTests/InstallUtilUT/InstallUtilUT.wixproj +++ b/src/UnitTests/InstallUtilUT/InstallUtilUT.wixproj @@ -1,21 +1,21 @@ - - - false - - - Release - 3.8 - - - - - - - $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll - PanelSwWixExtension - - - - - + + + false + + + Release + 3.8 + + + + + + + $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll + PanelSwWixExtension + + + + + \ No newline at end of file diff --git a/UnitTests/InstallUtilUT/InstallUtilUT.wxs b/src/UnitTests/InstallUtilUT/InstallUtilUT.wxs similarity index 100% rename from UnitTests/InstallUtilUT/InstallUtilUT.wxs rename to src/UnitTests/InstallUtilUT/InstallUtilUT.wxs diff --git a/UnitTests/IsWindowsVersionOrGreaterUT/IsWindowsVersionOrGreaterUT.wixproj b/src/UnitTests/IsWindowsVersionOrGreaterUT/IsWindowsVersionOrGreaterUT.wixproj similarity index 100% rename from UnitTests/IsWindowsVersionOrGreaterUT/IsWindowsVersionOrGreaterUT.wixproj rename to src/UnitTests/IsWindowsVersionOrGreaterUT/IsWindowsVersionOrGreaterUT.wixproj diff --git a/UnitTests/IsWindowsVersionOrGreaterUT/IsWindowsVersionOrGreaterUT.wxs b/src/UnitTests/IsWindowsVersionOrGreaterUT/IsWindowsVersionOrGreaterUT.wxs similarity index 100% rename from UnitTests/IsWindowsVersionOrGreaterUT/IsWindowsVersionOrGreaterUT.wxs rename to src/UnitTests/IsWindowsVersionOrGreaterUT/IsWindowsVersionOrGreaterUT.wxs diff --git a/UnitTests/JsonJPathUT/Json-Object.json b/src/UnitTests/JsonJPathUT/Json-Object.json similarity index 100% rename from UnitTests/JsonJPathUT/Json-Object.json rename to src/UnitTests/JsonJPathUT/Json-Object.json diff --git a/UnitTests/JsonJPathUT/JsonJPathUT.wixproj b/src/UnitTests/JsonJPathUT/JsonJPathUT.wixproj similarity index 100% rename from UnitTests/JsonJPathUT/JsonJPathUT.wixproj rename to src/UnitTests/JsonJPathUT/JsonJPathUT.wixproj diff --git a/UnitTests/JsonJPathUT/JsonJPathUT.wxs b/src/UnitTests/JsonJPathUT/JsonJPathUT.wxs similarity index 100% rename from UnitTests/JsonJPathUT/JsonJPathUT.wxs rename to src/UnitTests/JsonJPathUT/JsonJPathUT.wxs diff --git a/UnitTests/ListProcessorFeaturesUT/ListProcessorFeaturesUT.wixproj b/src/UnitTests/ListProcessorFeaturesUT/ListProcessorFeaturesUT.wixproj similarity index 100% rename from UnitTests/ListProcessorFeaturesUT/ListProcessorFeaturesUT.wixproj rename to src/UnitTests/ListProcessorFeaturesUT/ListProcessorFeaturesUT.wixproj diff --git a/UnitTests/ListProcessorFeaturesUT/ListProcessorFeaturesUT.wxs b/src/UnitTests/ListProcessorFeaturesUT/ListProcessorFeaturesUT.wxs similarity index 100% rename from UnitTests/ListProcessorFeaturesUT/ListProcessorFeaturesUT.wxs rename to src/UnitTests/ListProcessorFeaturesUT/ListProcessorFeaturesUT.wxs diff --git a/UnitTests/Md5HashUT/Md5HashUT.wixproj b/src/UnitTests/Md5HashUT/Md5HashUT.wixproj similarity index 100% rename from UnitTests/Md5HashUT/Md5HashUT.wixproj rename to src/UnitTests/Md5HashUT/Md5HashUT.wixproj diff --git a/UnitTests/Md5HashUT/Md5HashUT.wxs b/src/UnitTests/Md5HashUT/Md5HashUT.wxs similarity index 100% rename from UnitTests/Md5HashUT/Md5HashUT.wxs rename to src/UnitTests/Md5HashUT/Md5HashUT.wxs diff --git a/UnitTests/MsiSqlQueryUT/MsiSqlQueryUT.wixproj b/src/UnitTests/MsiSqlQueryUT/MsiSqlQueryUT.wixproj similarity index 97% rename from UnitTests/MsiSqlQueryUT/MsiSqlQueryUT.wixproj rename to src/UnitTests/MsiSqlQueryUT/MsiSqlQueryUT.wixproj index 77857a54..fbd2fa7a 100644 --- a/UnitTests/MsiSqlQueryUT/MsiSqlQueryUT.wixproj +++ b/src/UnitTests/MsiSqlQueryUT/MsiSqlQueryUT.wixproj @@ -1,20 +1,20 @@ - - - false - - - Release - 3.8 - - - - - - - - - $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll - PanelSwWixExtension - - + + + false + + + Release + 3.8 + + + + + + + + + $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll + PanelSwWixExtension + + \ No newline at end of file diff --git a/UnitTests/MsiSqlQueryUT/MsiSqlQueryUT.wxs b/src/UnitTests/MsiSqlQueryUT/MsiSqlQueryUT.wxs similarity index 100% rename from UnitTests/MsiSqlQueryUT/MsiSqlQueryUT.wxs rename to src/UnitTests/MsiSqlQueryUT/MsiSqlQueryUT.wxs diff --git a/UnitTests/PathSearchUT/PathSearchUT.wixproj b/src/UnitTests/PathSearchUT/PathSearchUT.wixproj similarity index 100% rename from UnitTests/PathSearchUT/PathSearchUT.wixproj rename to src/UnitTests/PathSearchUT/PathSearchUT.wixproj diff --git a/UnitTests/PathSearchUT/PathSearchUT.wxs b/src/UnitTests/PathSearchUT/PathSearchUT.wxs similarity index 100% rename from UnitTests/PathSearchUT/PathSearchUT.wxs rename to src/UnitTests/PathSearchUT/PathSearchUT.wxs diff --git a/UnitTests/PayloadUT/PayloadUT.wixproj b/src/UnitTests/PayloadUT/PayloadUT.wixproj similarity index 100% rename from UnitTests/PayloadUT/PayloadUT.wixproj rename to src/UnitTests/PayloadUT/PayloadUT.wixproj diff --git a/UnitTests/PayloadUT/PayloadUT.wxs b/src/UnitTests/PayloadUT/PayloadUT.wxs similarity index 100% rename from UnitTests/PayloadUT/PayloadUT.wxs rename to src/UnitTests/PayloadUT/PayloadUT.wxs diff --git a/UnitTests/PreprocessorUT/PreprocessorUT.wixproj b/src/UnitTests/PreprocessorUT/PreprocessorUT.wixproj similarity index 100% rename from UnitTests/PreprocessorUT/PreprocessorUT.wixproj rename to src/UnitTests/PreprocessorUT/PreprocessorUT.wixproj diff --git a/UnitTests/PreprocessorUT/PreprocessorUT.wxs b/src/UnitTests/PreprocessorUT/PreprocessorUT.wxs similarity index 100% rename from UnitTests/PreprocessorUT/PreprocessorUT.wxs rename to src/UnitTests/PreprocessorUT/PreprocessorUT.wxs diff --git a/UnitTests/PromptFileDowngradesUT/PromptFileDowngradesUT.wixproj b/src/UnitTests/PromptFileDowngradesUT/PromptFileDowngradesUT.wixproj similarity index 100% rename from UnitTests/PromptFileDowngradesUT/PromptFileDowngradesUT.wixproj rename to src/UnitTests/PromptFileDowngradesUT/PromptFileDowngradesUT.wixproj diff --git a/UnitTests/PromptFileDowngradesUT/PromptFileDowngradesUT.wxs b/src/UnitTests/PromptFileDowngradesUT/PromptFileDowngradesUT.wxs similarity index 100% rename from UnitTests/PromptFileDowngradesUT/PromptFileDowngradesUT.wxs rename to src/UnitTests/PromptFileDowngradesUT/PromptFileDowngradesUT.wxs diff --git a/UnitTests/ReadIniValuesUT/ReadIniValuesUT.wixproj b/src/UnitTests/ReadIniValuesUT/ReadIniValuesUT.wixproj old mode 100755 new mode 100644 similarity index 97% rename from UnitTests/ReadIniValuesUT/ReadIniValuesUT.wixproj rename to src/UnitTests/ReadIniValuesUT/ReadIniValuesUT.wixproj index 48a947e4..2dfd2e40 --- a/UnitTests/ReadIniValuesUT/ReadIniValuesUT.wixproj +++ b/src/UnitTests/ReadIniValuesUT/ReadIniValuesUT.wixproj @@ -1,24 +1,24 @@ - - - false - - - Release - 3.8 - - - - - - - - - - $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll - PanelSwWixExtension - - - - - + + + false + + + Release + 3.8 + + + + + + + + + + $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll + PanelSwWixExtension + + + + + \ No newline at end of file diff --git a/UnitTests/ReadIniValuesUT/ReadIniValuesUT.wxs b/src/UnitTests/ReadIniValuesUT/ReadIniValuesUT.wxs similarity index 100% rename from UnitTests/ReadIniValuesUT/ReadIniValuesUT.wxs rename to src/UnitTests/ReadIniValuesUT/ReadIniValuesUT.wxs diff --git a/UnitTests/ReadIniValuesUT/TEST.INI b/src/UnitTests/ReadIniValuesUT/TEST.INI old mode 100755 new mode 100644 similarity index 93% rename from UnitTests/ReadIniValuesUT/TEST.INI rename to src/UnitTests/ReadIniValuesUT/TEST.INI index 06296dad..80dfbda0 --- a/UnitTests/ReadIniValuesUT/TEST.INI +++ b/src/UnitTests/ReadIniValuesUT/TEST.INI @@ -1,3 +1,3 @@ - -[SECTION] + +[SECTION] VALUE=TEST_VALUE \ No newline at end of file diff --git a/UnitTests/RegexUT/RegexUT.wixproj b/src/UnitTests/RegexUT/RegexUT.wixproj similarity index 97% rename from UnitTests/RegexUT/RegexUT.wixproj rename to src/UnitTests/RegexUT/RegexUT.wixproj index b194f2cb..1ae90fde 100644 --- a/UnitTests/RegexUT/RegexUT.wixproj +++ b/src/UnitTests/RegexUT/RegexUT.wixproj @@ -1,23 +1,23 @@ - - - false - - - Release - 3.8 - - - - - - - $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll - PanelSwWixExtension - - - - - - - + + + false + + + Release + 3.8 + + + + + + + $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll + PanelSwWixExtension + + + + + + + \ No newline at end of file diff --git a/UnitTests/RegexUT/RegexUT.wxs b/src/UnitTests/RegexUT/RegexUT.wxs similarity index 100% rename from UnitTests/RegexUT/RegexUT.wxs rename to src/UnitTests/RegexUT/RegexUT.wxs diff --git a/UnitTests/RegexUT/Unicode.ini b/src/UnitTests/RegexUT/Unicode.ini similarity index 100% rename from UnitTests/RegexUT/Unicode.ini rename to src/UnitTests/RegexUT/Unicode.ini diff --git a/UnitTests/RemoveRegistryValueUT/RemoveRegistryValueUT.wixproj b/src/UnitTests/RemoveRegistryValueUT/RemoveRegistryValueUT.wixproj similarity index 97% rename from UnitTests/RemoveRegistryValueUT/RemoveRegistryValueUT.wixproj rename to src/UnitTests/RemoveRegistryValueUT/RemoveRegistryValueUT.wixproj index 817dbb97..ec923a06 100644 --- a/UnitTests/RemoveRegistryValueUT/RemoveRegistryValueUT.wixproj +++ b/src/UnitTests/RemoveRegistryValueUT/RemoveRegistryValueUT.wixproj @@ -1,21 +1,21 @@ - - - false - - - Release - 3.8 - - - - - - - $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll - PanelSwWixExtension - - - - - + + + false + + + Release + 3.8 + + + + + + + $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll + PanelSwWixExtension + + + + + \ No newline at end of file diff --git a/UnitTests/RemoveRegistryValueUT/RemoveRegistryValueUT.wxs b/src/UnitTests/RemoveRegistryValueUT/RemoveRegistryValueUT.wxs similarity index 100% rename from UnitTests/RemoveRegistryValueUT/RemoveRegistryValueUT.wxs rename to src/UnitTests/RemoveRegistryValueUT/RemoveRegistryValueUT.wxs diff --git a/UnitTests/RestartLocalResourcesUT/RestartLocalResourcesUT.wixproj b/src/UnitTests/RestartLocalResourcesUT/RestartLocalResourcesUT.wixproj similarity index 100% rename from UnitTests/RestartLocalResourcesUT/RestartLocalResourcesUT.wixproj rename to src/UnitTests/RestartLocalResourcesUT/RestartLocalResourcesUT.wixproj diff --git a/UnitTests/RestartLocalResourcesUT/RestartLocalResourcesUT.wxs b/src/UnitTests/RestartLocalResourcesUT/RestartLocalResourcesUT.wxs similarity index 100% rename from UnitTests/RestartLocalResourcesUT/RestartLocalResourcesUT.wxs rename to src/UnitTests/RestartLocalResourcesUT/RestartLocalResourcesUT.wxs diff --git a/UnitTests/ServiceConfigUT/ServiceConfigUT.wixproj b/src/UnitTests/ServiceConfigUT/ServiceConfigUT.wixproj similarity index 97% rename from UnitTests/ServiceConfigUT/ServiceConfigUT.wixproj rename to src/UnitTests/ServiceConfigUT/ServiceConfigUT.wixproj index 33c371a7..5d25f019 100644 --- a/UnitTests/ServiceConfigUT/ServiceConfigUT.wixproj +++ b/src/UnitTests/ServiceConfigUT/ServiceConfigUT.wixproj @@ -1,20 +1,20 @@ - - - false - - - Release - 3.8 - - - - - - - $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll - PanelSwWixExtension - - - - + + + false + + + Release + 3.8 + + + + + + + $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll + PanelSwWixExtension + + + + \ No newline at end of file diff --git a/UnitTests/ServiceConfigUT/ServiceConfigUT.wxs b/src/UnitTests/ServiceConfigUT/ServiceConfigUT.wxs similarity index 100% rename from UnitTests/ServiceConfigUT/ServiceConfigUT.wxs rename to src/UnitTests/ServiceConfigUT/ServiceConfigUT.wxs diff --git a/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/SetPropertyFromPipeBAF.cpp b/src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/SetPropertyFromPipeBAF.cpp similarity index 100% rename from UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/SetPropertyFromPipeBAF.cpp rename to src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/SetPropertyFromPipeBAF.cpp diff --git a/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/SetPropertyFromPipeBAF.vcxproj b/src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/SetPropertyFromPipeBAF.vcxproj similarity index 100% rename from UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/SetPropertyFromPipeBAF.vcxproj rename to src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/SetPropertyFromPipeBAF.vcxproj diff --git a/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/SetPropertyFromPipeBAF.vcxproj.filters b/src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/SetPropertyFromPipeBAF.vcxproj.filters similarity index 100% rename from UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/SetPropertyFromPipeBAF.vcxproj.filters rename to src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/SetPropertyFromPipeBAF.vcxproj.filters diff --git a/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/bafunctions.def b/src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/bafunctions.def similarity index 100% rename from UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/bafunctions.def rename to src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/bafunctions.def diff --git a/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/bafunctionsver.h b/src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/bafunctionsver.h similarity index 100% rename from UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/bafunctionsver.h rename to src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBAF/bafunctionsver.h diff --git a/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBootstrapper/SetPropertyFromPipeBootstrapper.wixproj b/src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBootstrapper/SetPropertyFromPipeBootstrapper.wixproj similarity index 100% rename from UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBootstrapper/SetPropertyFromPipeBootstrapper.wixproj rename to src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBootstrapper/SetPropertyFromPipeBootstrapper.wixproj diff --git a/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBootstrapper/SetPropertyFromPipeBootstrapper.wxs b/src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBootstrapper/SetPropertyFromPipeBootstrapper.wxs similarity index 100% rename from UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBootstrapper/SetPropertyFromPipeBootstrapper.wxs rename to src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeBootstrapper/SetPropertyFromPipeBootstrapper.wxs diff --git a/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeSetup/SetPropertyFromPipeSetup.wixproj b/src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeSetup/SetPropertyFromPipeSetup.wixproj similarity index 100% rename from UnitTests/SetPropertyFromPipe/SetPropertyFromPipeSetup/SetPropertyFromPipeSetup.wixproj rename to src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeSetup/SetPropertyFromPipeSetup.wixproj diff --git a/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeSetup/SetPropertyFromPipeSetup.wxs b/src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeSetup/SetPropertyFromPipeSetup.wxs similarity index 100% rename from UnitTests/SetPropertyFromPipe/SetPropertyFromPipeSetup/SetPropertyFromPipeSetup.wxs rename to src/UnitTests/SetPropertyFromPipe/SetPropertyFromPipeSetup/SetPropertyFromPipeSetup.wxs diff --git a/UnitTests/SplitFileUT/SplitFileUT.wixproj b/src/UnitTests/SplitFileUT/SplitFileUT.wixproj similarity index 100% rename from UnitTests/SplitFileUT/SplitFileUT.wixproj rename to src/UnitTests/SplitFileUT/SplitFileUT.wixproj diff --git a/UnitTests/SplitFileUT/SplitFileUT.wxs b/src/UnitTests/SplitFileUT/SplitFileUT.wxs similarity index 100% rename from UnitTests/SplitFileUT/SplitFileUT.wxs rename to src/UnitTests/SplitFileUT/SplitFileUT.wxs diff --git a/UnitTests/SqlSearchUT/Script.sql b/src/UnitTests/SqlSearchUT/Script.sql similarity index 100% rename from UnitTests/SqlSearchUT/Script.sql rename to src/UnitTests/SqlSearchUT/Script.sql diff --git a/UnitTests/SqlSearchUT/SqlSearchUT.wixproj b/src/UnitTests/SqlSearchUT/SqlSearchUT.wixproj similarity index 97% rename from UnitTests/SqlSearchUT/SqlSearchUT.wixproj rename to src/UnitTests/SqlSearchUT/SqlSearchUT.wixproj index 36813398..31a9a60b 100644 --- a/UnitTests/SqlSearchUT/SqlSearchUT.wixproj +++ b/src/UnitTests/SqlSearchUT/SqlSearchUT.wixproj @@ -1,24 +1,24 @@ - - - false - - - Release - 3.8 - - - - - - - $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll - PanelSwWixExtension - - - - - - - - + + + false + + + Release + 3.8 + + + + + + + $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll + PanelSwWixExtension + + + + + + + + \ No newline at end of file diff --git a/UnitTests/SqlSearchUT/SqlSearchUT.wxs b/src/UnitTests/SqlSearchUT/SqlSearchUT.wxs similarity index 100% rename from UnitTests/SqlSearchUT/SqlSearchUT.wxs rename to src/UnitTests/SqlSearchUT/SqlSearchUT.wxs diff --git a/UnitTests/StringUT/StringUT.wixproj b/src/UnitTests/StringUT/StringUT.wixproj similarity index 100% rename from UnitTests/StringUT/StringUT.wixproj rename to src/UnitTests/StringUT/StringUT.wixproj diff --git a/UnitTests/StringUT/StringUT.wxs b/src/UnitTests/StringUT/StringUT.wxs similarity index 100% rename from UnitTests/StringUT/StringUT.wxs rename to src/UnitTests/StringUT/StringUT.wxs diff --git a/UnitTests/TaskScheulerUT/SystemTask.xml b/src/UnitTests/TaskScheulerUT/SystemTask.xml similarity index 100% rename from UnitTests/TaskScheulerUT/SystemTask.xml rename to src/UnitTests/TaskScheulerUT/SystemTask.xml diff --git a/UnitTests/TaskScheulerUT/TaskSchedulerUT.wxs b/src/UnitTests/TaskScheulerUT/TaskSchedulerUT.wxs similarity index 100% rename from UnitTests/TaskScheulerUT/TaskSchedulerUT.wxs rename to src/UnitTests/TaskScheulerUT/TaskSchedulerUT.wxs diff --git a/UnitTests/TaskScheulerUT/TaskScheulerUT.wixproj b/src/UnitTests/TaskScheulerUT/TaskScheulerUT.wixproj similarity index 100% rename from UnitTests/TaskScheulerUT/TaskScheulerUT.wixproj rename to src/UnitTests/TaskScheulerUT/TaskScheulerUT.wixproj diff --git a/UnitTests/TelemetryUT/TelemetryUT.wixproj b/src/UnitTests/TelemetryUT/TelemetryUT.wixproj similarity index 97% rename from UnitTests/TelemetryUT/TelemetryUT.wixproj rename to src/UnitTests/TelemetryUT/TelemetryUT.wixproj index e332cdba..b0428972 100644 --- a/UnitTests/TelemetryUT/TelemetryUT.wixproj +++ b/src/UnitTests/TelemetryUT/TelemetryUT.wixproj @@ -1,21 +1,21 @@ - - - false - - - Release - 3.8 - - - - - - - $(BuildFolder)Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll - PanelSwWixExtension - - - - - + + + false + + + Release + 3.8 + + + + + + + $(BuildFolder)Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll + PanelSwWixExtension + + + + + \ No newline at end of file diff --git a/UnitTests/TelemetryUT/TelemetryUT.wxs b/src/UnitTests/TelemetryUT/TelemetryUT.wxs similarity index 100% rename from UnitTests/TelemetryUT/TelemetryUT.wxs rename to src/UnitTests/TelemetryUT/TelemetryUT.wxs diff --git a/UnitTests/VersionCompareUT/VersionCompareUT.wixproj b/src/UnitTests/VersionCompareUT/VersionCompareUT.wixproj similarity index 100% rename from UnitTests/VersionCompareUT/VersionCompareUT.wixproj rename to src/UnitTests/VersionCompareUT/VersionCompareUT.wixproj diff --git a/UnitTests/VersionCompareUT/VersionCompareUT.wxs b/src/UnitTests/VersionCompareUT/VersionCompareUT.wxs similarity index 100% rename from UnitTests/VersionCompareUT/VersionCompareUT.wxs rename to src/UnitTests/VersionCompareUT/VersionCompareUT.wxs diff --git a/UnitTests/WebsiteConfigUT/WebsiteConfigUT.wixproj b/src/UnitTests/WebsiteConfigUT/WebsiteConfigUT.wixproj similarity index 100% rename from UnitTests/WebsiteConfigUT/WebsiteConfigUT.wixproj rename to src/UnitTests/WebsiteConfigUT/WebsiteConfigUT.wixproj diff --git a/UnitTests/WebsiteConfigUT/WebsiteConfigUT.wxs b/src/UnitTests/WebsiteConfigUT/WebsiteConfigUT.wxs similarity index 100% rename from UnitTests/WebsiteConfigUT/WebsiteConfigUT.wxs rename to src/UnitTests/WebsiteConfigUT/WebsiteConfigUT.wxs diff --git a/UnitTests/WmiSearchUT/WmiSearchUT.wixproj b/src/UnitTests/WmiSearchUT/WmiSearchUT.wixproj similarity index 100% rename from UnitTests/WmiSearchUT/WmiSearchUT.wixproj rename to src/UnitTests/WmiSearchUT/WmiSearchUT.wixproj diff --git a/UnitTests/WmiSearchUT/WmiSearchUT.wxs b/src/UnitTests/WmiSearchUT/WmiSearchUT.wxs similarity index 100% rename from UnitTests/WmiSearchUT/WmiSearchUT.wxs rename to src/UnitTests/WmiSearchUT/WmiSearchUT.wxs diff --git a/UnitTests/XmlSearchUT/XSLTFile1.xslt b/src/UnitTests/XmlSearchUT/XSLTFile1.xslt similarity index 100% rename from UnitTests/XmlSearchUT/XSLTFile1.xslt rename to src/UnitTests/XmlSearchUT/XSLTFile1.xslt diff --git a/UnitTests/XmlSearchUT/XmlSearch.wxs b/src/UnitTests/XmlSearchUT/XmlSearch.wxs similarity index 100% rename from UnitTests/XmlSearchUT/XmlSearch.wxs rename to src/UnitTests/XmlSearchUT/XmlSearch.wxs diff --git a/UnitTests/XmlSearchUT/XmlSearchUT.wixproj b/src/UnitTests/XmlSearchUT/XmlSearchUT.wixproj similarity index 97% rename from UnitTests/XmlSearchUT/XmlSearchUT.wixproj rename to src/UnitTests/XmlSearchUT/XmlSearchUT.wixproj index 86ac0207..6a62036b 100644 --- a/UnitTests/XmlSearchUT/XmlSearchUT.wixproj +++ b/src/UnitTests/XmlSearchUT/XmlSearchUT.wixproj @@ -1,25 +1,25 @@ - - - false - - - Release - 3.8 - - - - Always - - - - - - - $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll - PanelSwWixExtension - - - - - + + + false + + + Release + 3.8 + + + + Always + + + + + + + $(BuildFolder)..\Any CPU\bin\$(Configuration)\PanelSwWixExtension\PanelSwWixExtension.dll + PanelSwWixExtension + + + + + \ No newline at end of file diff --git a/UnitTests/ZipFileUT/SizeZero.txt b/src/UnitTests/ZipFileUT/SizeZero.txt similarity index 100% rename from UnitTests/ZipFileUT/SizeZero.txt rename to src/UnitTests/ZipFileUT/SizeZero.txt diff --git a/UnitTests/ZipFileUT/ZipFileUT.wixproj b/src/UnitTests/ZipFileUT/ZipFileUT.wixproj similarity index 100% rename from UnitTests/ZipFileUT/ZipFileUT.wixproj rename to src/UnitTests/ZipFileUT/ZipFileUT.wixproj diff --git a/UnitTests/ZipFileUT/ZipFileUT.wxs b/src/UnitTests/ZipFileUT/ZipFileUT.wxs similarity index 100% rename from UnitTests/ZipFileUT/ZipFileUT.wxs rename to src/UnitTests/ZipFileUT/ZipFileUT.wxs diff --git a/dirs.proj b/src/dirs.proj similarity index 98% rename from dirs.proj rename to src/dirs.proj index a250d18b..3a779288 100644 --- a/dirs.proj +++ b/src/dirs.proj @@ -5,22 +5,22 @@ + - + - - + diff --git a/exprtk b/src/exprtk similarity index 100% rename from exprtk rename to src/exprtk diff --git a/global.json b/src/global.json similarity index 78% rename from global.json rename to src/global.json index 814b18fd..a456129d 100644 --- a/global.json +++ b/src/global.json @@ -1,7 +1,7 @@ { "msbuild-sdks": { "WixToolset.Sdk": "4.0.3", - "PanelSwWix4.Sdk": "5.0.0-psw-wix.0246-34", + "PanelSwWix4.Sdk": "5.0.0-psw-wix.0248-35", "Microsoft.Build.Traversal": "4.0.0" }, "sdk": { diff --git a/poco b/src/poco similarity index 100% rename from poco rename to src/poco diff --git a/protobuf b/src/protobuf similarity index 100% rename from protobuf rename to src/protobuf diff --git a/wixlib/PanelSwWixExtension.wxs b/src/wixlib/PanelSwWixExtension.wxs old mode 100755 new mode 100644 similarity index 97% rename from wixlib/PanelSwWixExtension.wxs rename to src/wixlib/PanelSwWixExtension.wxs index 1a022ed5..6d03c27c --- a/wixlib/PanelSwWixExtension.wxs +++ b/src/wixlib/PanelSwWixExtension.wxs @@ -1,965 +1,965 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wixlib/PanelSwWixLib.wixproj b/src/wixlib/PanelSwWixLib.wixproj old mode 100755 new mode 100644 similarity index 86% rename from wixlib/PanelSwWixLib.wixproj rename to src/wixlib/PanelSwWixLib.wixproj index da2a5f7c..9799d5f3 --- a/wixlib/PanelSwWixLib.wixproj +++ b/src/wixlib/PanelSwWixLib.wixproj @@ -1,22 +1,21 @@ - - - Library - PanelSwWixLib - true - true - Win32 - CaPlatform=$(CaPlatform);$(DefineConstants) - EnableZipContainer=1;$(DefineConstants) - - - - - - - - - - - - - + + + Library + PanelSwWixLib + true + true + BaseBuildFolder=$(BaseBuildFolder);$(DefineConstants) + EnableZipContainer=1;$(DefineConstants) + + + + + + + + + + + + + diff --git a/wixlib/en-US.wxl b/src/wixlib/en-US.wxl old mode 100755 new mode 100644 similarity index 98% rename from wixlib/en-US.wxl rename to src/wixlib/en-US.wxl index 5d2a1ce7..71791276 --- a/wixlib/en-US.wxl +++ b/src/wixlib/en-US.wxl @@ -1,65 +1,65 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wixlib/he-IL.wxl b/src/wixlib/he-IL.wxl similarity index 100% rename from wixlib/he-IL.wxl rename to src/wixlib/he-IL.wxl