aboutsummaryrefslogtreecommitdiff
path: root/src/dutil/srputil.cpp
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2017-09-03 11:22:38 -0700
committerRob Mensching <rob@firegiant.com>2017-09-03 13:33:33 -0700
commit5d8375007754101ff2889d0e79486c8f9b7cf5ab (patch)
treea76d6fb6a38dd9f04a93ffcfd9d64e76779b3414 /src/dutil/srputil.cpp
parent8e8da6dbc051ec884b5d439bb4f44dc027d05bbf (diff)
downloadwix-5d8375007754101ff2889d0e79486c8f9b7cf5ab.tar.gz
wix-5d8375007754101ff2889d0e79486c8f9b7cf5ab.tar.bz2
wix-5d8375007754101ff2889d0e79486c8f9b7cf5ab.zip
Initial commit
Diffstat (limited to 'src/dutil/srputil.cpp')
-rw-r--r--src/dutil/srputil.cpp237
1 files changed, 237 insertions, 0 deletions
diff --git a/src/dutil/srputil.cpp b/src/dutil/srputil.cpp
new file mode 100644
index 00000000..9fc2f94a
--- /dev/null
+++ b/src/dutil/srputil.cpp
@@ -0,0 +1,237 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3#include "precomp.h"
4
5
6typedef BOOL (WINAPI *PFN_SETRESTOREPTW)(
7 __in PRESTOREPOINTINFOW pRestorePtSpec,
8 __out PSTATEMGRSTATUS pSMgrStatus
9 );
10
11static PFN_SETRESTOREPTW vpfnSRSetRestorePointW = NULL;
12static HMODULE vhSrClientDll = NULL;
13
14
15static HRESULT InitializeComSecurity();
16
17
18DAPI_(HRESULT) SrpInitialize(
19 __in BOOL fInitializeComSecurity
20 )
21{
22 HRESULT hr = S_OK;
23
24 hr = LoadSystemLibrary(L"srclient.dll", &vhSrClientDll);
25 if (FAILED(hr))
26 {
27 ExitFunction1(hr = E_NOTIMPL);
28 }
29
30 vpfnSRSetRestorePointW = reinterpret_cast<PFN_SETRESTOREPTW>(::GetProcAddress(vhSrClientDll, "SRSetRestorePointW"));
31 ExitOnNullWithLastError(vpfnSRSetRestorePointW, hr, "Failed to find set restore point proc address.");
32
33 // If allowed, initialize COM security to enable NetworkService,
34 // LocalService and System to make callbacks to the process
35 // calling System Restore. This is required for any process
36 // that calls SRSetRestorePoint.
37 if (fInitializeComSecurity)
38 {
39 hr = InitializeComSecurity();
40 ExitOnFailure(hr, "Failed to initialize security for COM to talk to system restore.");
41 }
42
43LExit:
44 if (FAILED(hr) && vhSrClientDll)
45 {
46 SrpUninitialize();
47 }
48
49 return hr;
50}
51
52DAPI_(void) SrpUninitialize()
53{
54 if (vhSrClientDll)
55 {
56 ::FreeLibrary(vhSrClientDll);
57 vhSrClientDll = NULL;
58 vpfnSRSetRestorePointW = NULL;
59 }
60}
61
62DAPI_(HRESULT) SrpCreateRestorePoint(
63 __in_z LPCWSTR wzApplicationName,
64 __in SRP_ACTION action
65 )
66{
67 HRESULT hr = S_OK;
68 RESTOREPOINTINFOW restorePoint = { };
69 STATEMGRSTATUS status = { };
70
71 if (!vpfnSRSetRestorePointW)
72 {
73 ExitFunction1(hr = E_NOTIMPL);
74 }
75
76 restorePoint.dwEventType = BEGIN_SYSTEM_CHANGE;
77 restorePoint.dwRestorePtType = (SRP_ACTION_INSTALL == action) ? APPLICATION_INSTALL : (SRP_ACTION_UNINSTALL == action) ? APPLICATION_UNINSTALL : MODIFY_SETTINGS;
78 ::StringCbCopyW(restorePoint.szDescription, sizeof(restorePoint.szDescription), wzApplicationName);
79
80 if (!vpfnSRSetRestorePointW(&restorePoint, &status))
81 {
82 ExitOnWin32Error(status.nStatus, hr, "Failed to create system restore point.");
83 }
84
85LExit:
86 return hr;
87}
88
89
90// internal functions.
91
92static HRESULT InitializeComSecurity()
93{
94 HRESULT hr = S_OK;
95 DWORD er = ERROR_SUCCESS;
96 SECURITY_DESCRIPTOR sd = {0};
97 EXPLICIT_ACCESS ea[5] = {0};
98 ACL* pAcl = NULL;
99 ULONGLONG rgSidBA[(SECURITY_MAX_SID_SIZE+sizeof(ULONGLONG)-1)/sizeof(ULONGLONG)]={0};
100 ULONGLONG rgSidLS[(SECURITY_MAX_SID_SIZE+sizeof(ULONGLONG)-1)/sizeof(ULONGLONG)]={0};
101 ULONGLONG rgSidNS[(SECURITY_MAX_SID_SIZE+sizeof(ULONGLONG)-1)/sizeof(ULONGLONG)]={0};
102 ULONGLONG rgSidPS[(SECURITY_MAX_SID_SIZE+sizeof(ULONGLONG)-1)/sizeof(ULONGLONG)]={0};
103 ULONGLONG rgSidSY[(SECURITY_MAX_SID_SIZE+sizeof(ULONGLONG)-1)/sizeof(ULONGLONG)]={0};
104 DWORD cbSid = 0;
105
106 // Create the security descriptor explicitly as follows because
107 // CoInitializeSecurity() will not accept the relative security descriptors
108 // returned by ConvertStringSecurityDescriptorToSecurityDescriptor().
109 //
110 // The result is a security descriptor that is equivalent to the following
111 // security descriptor definition language (SDDL) string:
112 //
113 // O:BAG:BAD:(A;;0x1;;;LS)(A;;0x1;;;NS)(A;;0x1;;;PS)(A;;0x1;;;SY)(A;;0x1;;;BA)
114 //
115
116 // Initialize the security descriptor.
117 if (!::InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
118 {
119 ExitWithLastError(hr, "Failed to initialize security descriptor for system restore.");
120 }
121
122 // Create an administrator group security identifier (SID).
123 cbSid = sizeof(rgSidBA);
124 if (!::CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, rgSidBA, &cbSid))
125 {
126 ExitWithLastError(hr, "Failed to create administrator SID for system restore.");
127 }
128
129 // Create a local service security identifier (SID).
130 cbSid = sizeof(rgSidLS);
131 if (!::CreateWellKnownSid(WinLocalServiceSid, NULL, rgSidLS, &cbSid))
132 {
133 ExitWithLastError(hr, "Failed to create local service SID for system restore.");
134 }
135
136 // Create a network service security identifier (SID).
137 cbSid = sizeof(rgSidNS);
138 if (!::CreateWellKnownSid(WinNetworkServiceSid, NULL, rgSidNS, &cbSid))
139 {
140 ExitWithLastError(hr, "Failed to create network service SID for system restore.");
141 }
142
143 // Create a personal account security identifier (SID).
144 cbSid = sizeof(rgSidPS);
145 if (!::CreateWellKnownSid(WinSelfSid, NULL, rgSidPS, &cbSid))
146 {
147 ExitWithLastError(hr, "Failed to create self SID for system restore.");
148 }
149
150 // Create a local service security identifier (SID).
151 cbSid = sizeof(rgSidSY);
152 if (!::CreateWellKnownSid(WinLocalSystemSid, NULL, rgSidSY, &cbSid))
153 {
154 ExitWithLastError(hr, "Failed to create local system SID for system restore.");
155 }
156
157 // Setup the access control entries (ACE) for COM. COM_RIGHTS_EXECUTE and
158 // COM_RIGHTS_EXECUTE_LOCAL are the minimum access rights required.
159 ea[0].grfAccessPermissions = COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL;
160 ea[0].grfAccessMode = SET_ACCESS;
161 ea[0].grfInheritance = NO_INHERITANCE;
162 ea[0].Trustee.pMultipleTrustee = NULL;
163 ea[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
164 ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
165 ea[0].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
166 ea[0].Trustee.ptstrName = (LPTSTR)rgSidBA;
167
168 ea[1].grfAccessPermissions = COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL;
169 ea[1].grfAccessMode = SET_ACCESS;
170 ea[1].grfInheritance = NO_INHERITANCE;
171 ea[1].Trustee.pMultipleTrustee = NULL;
172 ea[1].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
173 ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
174 ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
175 ea[1].Trustee.ptstrName = (LPTSTR)rgSidLS;
176
177 ea[2].grfAccessPermissions = COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL;
178 ea[2].grfAccessMode = SET_ACCESS;
179 ea[2].grfInheritance = NO_INHERITANCE;
180 ea[2].Trustee.pMultipleTrustee = NULL;
181 ea[2].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
182 ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID;
183 ea[2].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
184 ea[2].Trustee.ptstrName = (LPTSTR)rgSidNS;
185
186 ea[3].grfAccessPermissions = COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL;
187 ea[3].grfAccessMode = SET_ACCESS;
188 ea[3].grfInheritance = NO_INHERITANCE;
189 ea[3].Trustee.pMultipleTrustee = NULL;
190 ea[3].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
191 ea[3].Trustee.TrusteeForm = TRUSTEE_IS_SID;
192 ea[3].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
193 ea[3].Trustee.ptstrName = (LPTSTR)rgSidPS;
194
195 ea[4].grfAccessPermissions = COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL;
196 ea[4].grfAccessMode = SET_ACCESS;
197 ea[4].grfInheritance = NO_INHERITANCE;
198 ea[4].Trustee.pMultipleTrustee = NULL;
199 ea[4].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
200 ea[4].Trustee.TrusteeForm = TRUSTEE_IS_SID;
201 ea[4].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
202 ea[4].Trustee.ptstrName = (LPTSTR)rgSidSY;
203
204 // Create an access control list (ACL) using this ACE list.
205 er = ::SetEntriesInAcl(countof(ea), ea, NULL, &pAcl);
206 ExitOnWin32Error(er, hr, "Failed to create ACL for system restore.");
207
208 // Set the security descriptor owner to Administrators.
209 if (!::SetSecurityDescriptorOwner(&sd, rgSidBA, FALSE))
210 {
211 ExitWithLastError(hr, "Failed to set administrators owner for system restore.");
212 }
213
214 // Set the security descriptor group to Administrators.
215 if (!::SetSecurityDescriptorGroup(&sd, rgSidBA, FALSE))
216 {
217 ExitWithLastError(hr, "Failed to set administrators group access for system restore.");
218 }
219
220 // Set the discretionary access control list (DACL) to the ACL.
221 if (!::SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE))
222 {
223 ExitWithLastError(hr, "Failed to set DACL for system restore.");
224 }
225
226 // Note that an explicit security descriptor is being passed in.
227 hr= ::CoInitializeSecurity(&sd, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_DISABLE_AAA | EOAC_NO_CUSTOM_MARSHAL, NULL);
228 ExitOnFailure(hr, "Failed to initialize COM security for system restore.");
229
230LExit:
231 if (pAcl)
232 {
233 ::LocalFree(pAcl);
234 }
235
236 return hr;
237}