1
// TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2021 - TortoiseGit
4 // Copyright (C) 2021 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include <winrt/Windows.Management.Deployment.h>
24 #include <winrt/Windows.Foundation.Collections.h>
25 #include <winrt/Windows.ApplicationModel.h>
27 #pragma comment(lib, "windowsapp.lib")
29 using namespace winrt::Windows::Foundation
;
30 using namespace winrt::Windows::Management::Deployment
;
32 BOOL APIENTRY
DllMain(HANDLE
/*hModule*/, DWORD
/*ul_reason_for_call*/, LPVOID
/*lpReserved*/)
37 UINT __stdcall
RegisterSparsePackage(MSIHANDLE hModule
)
40 wchar_t emptyBuf
[1]{};
41 MsiGetPropertyW(hModule
, L
"INSTALLDIR", emptyBuf
, &len
);
42 auto sparseExtPath
= std::make_unique
<wchar_t[]>(len
+ 1LL);
44 MsiGetPropertyW(hModule
, L
"INSTALLDIR", sparseExtPath
.get(), &len
);
47 MsiGetPropertyW(hModule
, L
"SPARSEPACKAGEFILE", emptyBuf
, &len
);
48 auto sparsePackageFile
= std::make_unique
<wchar_t[]>(len
+ 1LL);
50 MsiGetPropertyW(hModule
, L
"SPARSEPACKAGEFILE", sparsePackageFile
.get(), &len
);
52 std::wstring sSparsePackagePath
= sparseExtPath
.get();
53 sSparsePackagePath
+= L
"\\bin\\";
54 sSparsePackagePath
+= sparsePackageFile
.get();
56 PackageManager manager
;
57 AddPackageOptions options
;
58 Uri
externalUri(sparseExtPath
.get());
59 Uri
packageUri(sSparsePackagePath
.c_str());
60 options
.ExternalLocationUri(externalUri
);
61 auto deploymentOperation
= manager
.AddPackageByUriAsync(packageUri
, options
);
63 auto deployResult
= deploymentOperation
.get();
65 if (!SUCCEEDED(deployResult
.ExtendedErrorCode()))
68 PMSIHANDLE hRecord
= MsiCreateRecord(0);
69 std::wstring error
= L
"AddPackageByUriAsync failed (Errorcode: ";
70 error
+= std::to_wstring(deployResult
.ExtendedErrorCode());
72 error
+= deployResult
.ErrorText();
73 MsiRecordSetStringW(hRecord
, 0, error
.c_str());
74 MsiProcessMessage(hModule
, INSTALLMESSAGE_ERROR
, hRecord
);
75 MsiCloseHandle(hRecord
);
80 UINT __stdcall
UnregisterSparsePackage(MSIHANDLE hModule
)
83 wchar_t emptyBuf
[1]{};
84 MsiGetPropertyW(hModule
, L
"SPARSEPACKAGENAME", emptyBuf
, &len
);
85 auto sparsePackageName
= std::make_unique
<wchar_t[]>(len
+ 1LL);
87 MsiGetPropertyW(hModule
, L
"SPARSEPACKAGENAME", sparsePackageName
.get(), &len
);
89 PackageManager packageManager
;
90 winrt::Windows::Foundation::Collections::IIterable
<winrt::Windows::ApplicationModel::Package
> packages
;
93 packages
= packageManager
.FindPackagesForUser(L
"");
95 catch (winrt::hresult_error
const& ex
)
97 PMSIHANDLE hRecord
= MsiCreateRecord(0);
98 std::wstring error
= L
"FindPackagesForUser failed (Errorcode: ";
99 error
+= std::to_wstring(ex
.code().value
);
101 error
+= ex
.message();
102 MsiRecordSetStringW(hRecord
, 0, error
.c_str());
103 MsiProcessMessage(hModule
, INSTALLMESSAGE_ERROR
, hRecord
);
104 MsiCloseHandle(hRecord
);
106 return ERROR_SUCCESS
;
109 for (const auto& package
: packages
)
111 if (package
.Id().Name() != sparsePackageName
.get())
114 winrt::hstring fullName
= package
.Id().FullName();
115 auto deploymentOperation
= packageManager
.RemovePackageAsync(fullName
, RemovalOptions::None
);
116 auto deployResult
= deploymentOperation
.get();
117 if (SUCCEEDED(deployResult
.ExtendedErrorCode()))
120 // Undeployment failed
121 PMSIHANDLE hRecord
= MsiCreateRecord(0);
122 std::wstring error
= L
"RemovePackageAsync failed (Errorcode: ";
123 error
+= std::to_wstring(deployResult
.ExtendedErrorCode());
125 error
+= deployResult
.ErrorText();
126 MsiRecordSetStringW(hRecord
, 0, error
.c_str());
127 MsiProcessMessage(hModule
, INSTALLMESSAGE_ERROR
, hRecord
);
128 MsiCloseHandle(hRecord
);
131 return ERROR_SUCCESS
;