diff options
Diffstat (limited to 'src/ext/Util/ca/scasmbsched.cpp')
-rw-r--r-- | src/ext/Util/ca/scasmbsched.cpp | 639 |
1 files changed, 639 insertions, 0 deletions
diff --git a/src/ext/Util/ca/scasmbsched.cpp b/src/ext/Util/ca/scasmbsched.cpp new file mode 100644 index 00000000..e29f7f51 --- /dev/null +++ b/src/ext/Util/ca/scasmbsched.cpp | |||
@@ -0,0 +1,639 @@ | |||
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 | |||
6 | /******************************************************************** | ||
7 | Helper functions to maintain a list of file shares to create / remove | ||
8 | |||
9 | ********************************************************************/ | ||
10 | SCA_SMB* NewSmb() | ||
11 | { | ||
12 | SCA_SMB* pss = (SCA_SMB*)MemAlloc(sizeof(SCA_SMB), TRUE); | ||
13 | Assert(pss); | ||
14 | return pss; | ||
15 | } | ||
16 | |||
17 | |||
18 | SCA_SMB_EX_USER_PERMS* NewExUserPermsSmb() | ||
19 | { | ||
20 | SCA_SMB_EX_USER_PERMS* pExUserPerms = (SCA_SMB_EX_USER_PERMS*)MemAlloc(sizeof(SCA_SMB_EX_USER_PERMS), TRUE); | ||
21 | Assert(pExUserPerms); | ||
22 | return pExUserPerms; | ||
23 | } | ||
24 | |||
25 | |||
26 | SCA_SMB* AddSmbToList(SCA_SMB* pssList, SCA_SMB* pss) | ||
27 | { | ||
28 | if (pssList) | ||
29 | { | ||
30 | SCA_SMB* pssT = pssList; | ||
31 | while (pssT->pssNext) | ||
32 | { | ||
33 | pssT = pssT->pssNext; | ||
34 | } | ||
35 | |||
36 | pssT->pssNext = pss; | ||
37 | } | ||
38 | else | ||
39 | { | ||
40 | pssList = pss; | ||
41 | } | ||
42 | |||
43 | return pssList; | ||
44 | } | ||
45 | |||
46 | |||
47 | SCA_SMB_EX_USER_PERMS* AddExUserPermsSmbToList( | ||
48 | SCA_SMB_EX_USER_PERMS* pExUserPermsList, | ||
49 | SCA_SMB_EX_USER_PERMS* pExUserPerms | ||
50 | ) | ||
51 | { | ||
52 | SCA_SMB_EX_USER_PERMS* pExUserPermsTemp = pExUserPermsList; | ||
53 | if (pExUserPermsList) | ||
54 | { | ||
55 | while (pExUserPermsTemp->pExUserPermsNext) | ||
56 | { | ||
57 | pExUserPermsTemp = pExUserPermsTemp->pExUserPermsNext; | ||
58 | } | ||
59 | |||
60 | pExUserPermsTemp->pExUserPermsNext = pExUserPerms; | ||
61 | } | ||
62 | else | ||
63 | { | ||
64 | pExUserPermsList = pExUserPerms; | ||
65 | } | ||
66 | |||
67 | return pExUserPermsList; | ||
68 | } | ||
69 | |||
70 | void ScaSmbFreeList(SCA_SMB* pssList) | ||
71 | { | ||
72 | SCA_SMB* pssDelete = pssList; | ||
73 | while (pssList) | ||
74 | { | ||
75 | pssDelete = pssList; | ||
76 | pssList = pssList->pssNext; | ||
77 | |||
78 | MemFree(pssDelete); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | void ScaExUserPermsSmbFreeList(SCA_SMB_EX_USER_PERMS* pExUserPermsList) | ||
83 | { | ||
84 | SCA_SMB_EX_USER_PERMS* pExUserPermsDelete = pExUserPermsList; | ||
85 | while (pExUserPermsList) | ||
86 | { | ||
87 | pExUserPermsDelete = pExUserPermsList; | ||
88 | pExUserPermsList = pExUserPermsList->pExUserPermsNext; | ||
89 | |||
90 | MemFree(pExUserPermsDelete); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | // sql query constants | ||
95 | LPCWSTR vcsSmbQuery = L"SELECT `Wix4FileShare`, `ShareName`, `Description`, `Directory_`, " | ||
96 | L"`Component_`, `User_`, `Permissions` FROM `Wix4FileShare`"; | ||
97 | |||
98 | enum eSmbQuery { | ||
99 | ssqFileShare = 1, | ||
100 | ssqShareName, | ||
101 | ssqDescription, | ||
102 | ssqDirectory, | ||
103 | ssqComponent, | ||
104 | ssqUser, | ||
105 | ssqPermissions | ||
106 | }; | ||
107 | |||
108 | |||
109 | /******************************************************************** | ||
110 | ScaSmbRead - read all of the information from the msi tables and | ||
111 | return a list of file share jobs to be done. | ||
112 | |||
113 | ********************************************************************/ | ||
114 | HRESULT ScaSmbRead(SCA_SMB** ppssList) | ||
115 | { | ||
116 | HRESULT hr = S_OK; | ||
117 | UINT er = ERROR_SUCCESS; | ||
118 | PMSIHANDLE hView, hRec; | ||
119 | |||
120 | LPWSTR pwzData = NULL; | ||
121 | |||
122 | SCA_SMB* pss = NULL; | ||
123 | BOOL bUserPermissionsTableExists = FALSE; | ||
124 | |||
125 | if (S_OK != WcaTableExists(L"Wix4FileShare")) | ||
126 | { | ||
127 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaSmbCreateShare() - Wix4FileShare table not present"); | ||
128 | ExitFunction1(hr = S_FALSE); | ||
129 | } | ||
130 | |||
131 | if (S_OK == WcaTableExists(L"Wix4FileSharePermissions")) | ||
132 | { | ||
133 | bUserPermissionsTableExists = TRUE; | ||
134 | } | ||
135 | else | ||
136 | { | ||
137 | WcaLog(LOGMSG_VERBOSE, "No Additional Permissions - Wix4FileSharePermissions table not present"); | ||
138 | } | ||
139 | |||
140 | WcaLog(LOGMSG_VERBOSE, "Reading File Share Tables"); | ||
141 | |||
142 | // loop through all the fileshares | ||
143 | hr = WcaOpenExecuteView(vcsSmbQuery, &hView); | ||
144 | ExitOnFailure(hr, "Failed to open view on Wix4FileShare table"); | ||
145 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
146 | { | ||
147 | pss = NewSmb(); | ||
148 | if (!pss) | ||
149 | { | ||
150 | hr = E_OUTOFMEMORY; | ||
151 | break; | ||
152 | } | ||
153 | Assert(pss); | ||
154 | ::ZeroMemory(pss, sizeof(*pss)); | ||
155 | |||
156 | hr = WcaGetRecordString(hRec, ssqFileShare, &pwzData); | ||
157 | ExitOnFailure(hr, "Failed to get Wix4FileShare.Wix4FileShare"); | ||
158 | hr = ::StringCchCopyW(pss->wzId, countof(pss->wzId), pwzData); | ||
159 | ExitOnFailure(hr, "Failed to copy ID string to smb object"); | ||
160 | |||
161 | hr = WcaGetRecordFormattedString(hRec, ssqShareName, &pwzData); | ||
162 | ExitOnFailure(hr, "Failed to get Wix4FileShare.ShareName"); | ||
163 | hr = ::StringCchCopyW(pss->wzShareName, countof(pss->wzShareName), pwzData); | ||
164 | ExitOnFailure(hr, "Failed to copy share name string to smb object"); | ||
165 | |||
166 | hr = WcaGetRecordString(hRec, ssqComponent, &pwzData); | ||
167 | ExitOnFailure(hr, "Failed to get Component for Wix4FileShare: '%ls'", pss->wzShareName); | ||
168 | hr = ::StringCchCopyW(pss->wzComponent, countof(pss->wzComponent), pwzData); | ||
169 | ExitOnFailure(hr, "Failed to copy component string to smb object"); | ||
170 | |||
171 | hr = WcaGetRecordFormattedString(hRec, ssqDescription, &pwzData); | ||
172 | ExitOnFailure(hr, "Failed to get Share Description for Wix4FileShare: '%ls'", pss->wzShareName); | ||
173 | hr = ::StringCchCopyW(pss->wzDescription, countof(pss->wzDescription), pwzData); | ||
174 | ExitOnFailure(hr, "Failed to copy description string to smb object"); | ||
175 | |||
176 | // get user info from the user table | ||
177 | hr = WcaGetRecordFormattedString(hRec, ssqUser, &pwzData); | ||
178 | ExitOnFailure(hr, "Failed to get Wix4User record for Wix4FileShare: '%ls'", pss->wzShareName); | ||
179 | |||
180 | // get component install state | ||
181 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pss->wzComponent, &pss->isInstalled, &pss->isAction); | ||
182 | hr = HRESULT_FROM_WIN32(er); | ||
183 | ExitOnFailure(hr, "Failed to get Component state for Wix4FileShare"); | ||
184 | |||
185 | // if a user was specified | ||
186 | if (*pwzData) | ||
187 | { | ||
188 | pss->fUseIntegratedAuth = FALSE; | ||
189 | pss->fLegacyUserProvided = TRUE; | ||
190 | hr = ScaGetUser(pwzData, &pss->scau); | ||
191 | ExitOnFailure(hr, "Failed to get user information for fileshare: '%ls'", pss->wzShareName); | ||
192 | } | ||
193 | else | ||
194 | { | ||
195 | pss->fLegacyUserProvided = FALSE; | ||
196 | // TODO: figure out whether this is useful still | ||
197 | //pss->fUseIntegratedAuth = TRUE; | ||
198 | // integrated authorization doesn't have a User record | ||
199 | } | ||
200 | |||
201 | // get the share's directory | ||
202 | hr = WcaGetRecordString(hRec, ssqDirectory, &pwzData); | ||
203 | ExitOnFailure(hr, "Failed to get directory for Wix4FileShare: '%ls'", pss->wzShareName); | ||
204 | |||
205 | WCHAR wzPath[MAX_PATH]; | ||
206 | DWORD dwLen; | ||
207 | dwLen = countof(wzPath); | ||
208 | // review: relevant for file shares? | ||
209 | if (INSTALLSTATE_SOURCE == pss->isAction) | ||
210 | { | ||
211 | er = ::MsiGetSourcePathW(WcaGetInstallHandle(), pwzData, wzPath, &dwLen); | ||
212 | } | ||
213 | else | ||
214 | { | ||
215 | er = ::MsiGetTargetPathW(WcaGetInstallHandle(), pwzData, wzPath, &dwLen); | ||
216 | } | ||
217 | hr = HRESULT_FROM_WIN32(er); | ||
218 | ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory"); | ||
219 | |||
220 | // If the path is to the root of a drive, then it needs a trailing backslash. | ||
221 | // Otherwise, it can't have a trailing backslash. | ||
222 | if (3 < dwLen) | ||
223 | { | ||
224 | if (wzPath[dwLen - 1] == L'\\') | ||
225 | { | ||
226 | wzPath[dwLen - 1] = 0; | ||
227 | } | ||
228 | } | ||
229 | else if (2 == dwLen && wzPath[1] == L':') | ||
230 | { | ||
231 | wzPath[2] = L'\\'; | ||
232 | wzPath[3] = 0; | ||
233 | } | ||
234 | |||
235 | hr = ::StringCchCopyW(pss->wzDirectory, countof(pss->wzDirectory), wzPath); | ||
236 | ExitOnFailure(hr, "Failed to copy directory string to smb object"); | ||
237 | |||
238 | hr = WcaGetRecordInteger(hRec, ssqPermissions, &pss->nPermissions); | ||
239 | ExitOnFailure(hr, "Failed to get Wix4FileShare.Permissions"); | ||
240 | |||
241 | // Check to see if additional user & permissions are specified for this share | ||
242 | if (bUserPermissionsTableExists) | ||
243 | { | ||
244 | hr = ScaSmbExPermsRead(pss); | ||
245 | ExitOnFailure(hr, "Failed to get Additional File Share Permissions"); | ||
246 | } | ||
247 | |||
248 | *ppssList = AddSmbToList(*ppssList, pss); | ||
249 | pss = NULL; // set the smb NULL so it doesn't accidentally get freed below | ||
250 | } | ||
251 | |||
252 | if (E_NOMOREITEMS == hr) | ||
253 | { | ||
254 | hr = S_OK; | ||
255 | } | ||
256 | ExitOnFailure(hr, "Failure occured while processing Wix4FileShare table"); | ||
257 | |||
258 | LExit: | ||
259 | // if anything was left over after an error clean it all up | ||
260 | if (pss) | ||
261 | { | ||
262 | ScaSmbFreeList(pss); | ||
263 | } | ||
264 | |||
265 | ReleaseStr(pwzData); | ||
266 | |||
267 | return hr; | ||
268 | } | ||
269 | |||
270 | |||
271 | /******************************************************************** | ||
272 | RetrieveSMBShareUserPermList - retrieve SMB Share's user permission list | ||
273 | |||
274 | ********************************************************************/ | ||
275 | HRESULT RetrieveFileShareUserPerm(SCA_SMB* pss, SCA_SMB_EX_USER_PERMS** ppExUserPermsList, DWORD *pUserPermsCount) | ||
276 | { | ||
277 | HRESULT hr = S_OK; | ||
278 | SHARE_INFO_502* psi = NULL; | ||
279 | NET_API_STATUS s; | ||
280 | BOOL bValid, bDaclDefaulted; | ||
281 | PACL acl = NULL; | ||
282 | PEXPLICIT_ACCESSW pEA = NULL; | ||
283 | ULONG nCount = 0; | ||
284 | DWORD er = ERROR_SUCCESS; | ||
285 | PSID pSID = NULL; | ||
286 | DWORD nUserNameSize = MAX_DARWIN_COLUMN; | ||
287 | DWORD nDomainNameSize = MAX_DARWIN_COLUMN; | ||
288 | SID_NAME_USE peUse; | ||
289 | DWORD dwCounter = 0; | ||
290 | SCA_SMB_EX_USER_PERMS* pExUserPermsList = NULL; | ||
291 | DWORD dwUserPermsCount = 0; | ||
292 | |||
293 | *pUserPermsCount = 0; | ||
294 | s = ::NetShareGetInfo(NULL, pss->wzShareName, 502, (LPBYTE*)&psi); | ||
295 | WcaLog(LOGMSG_VERBOSE, "retrieving permissions on existing file share."); | ||
296 | if (NERR_NetNameNotFound == s) | ||
297 | { | ||
298 | WcaLog(LOGMSG_VERBOSE, "File share has already been removed."); | ||
299 | ExitFunction1(hr = S_OK); | ||
300 | } | ||
301 | else if (NERR_Success != s || psi == NULL) | ||
302 | { | ||
303 | hr = E_FAIL; | ||
304 | ExitOnFailure(hr, "Failed to get share information with return code: %d", s); | ||
305 | } | ||
306 | if (!::GetSecurityDescriptorDacl(psi->shi502_security_descriptor, &bValid, &acl, &bDaclDefaulted) || !bValid) | ||
307 | { | ||
308 | ExitOnLastError(hr, "Failed to get acl from security descriptor"); | ||
309 | } | ||
310 | |||
311 | er = ::GetExplicitEntriesFromAclW(acl, &nCount, &pEA); | ||
312 | hr = HRESULT_FROM_WIN32(er); | ||
313 | ExitOnFailure(hr, "Failed to get access entries from acl for file share %ls", pss->wzShareName); | ||
314 | for (dwCounter = 0; dwCounter < nCount; ++dwCounter) | ||
315 | { | ||
316 | if (TRUSTEE_IS_SID == pEA[dwCounter].Trustee.TrusteeForm) | ||
317 | { | ||
318 | SCA_SMB_EX_USER_PERMS* pExUserPerms = NewExUserPermsSmb(); | ||
319 | ::ZeroMemory(pExUserPerms, sizeof(*pExUserPerms)); | ||
320 | pExUserPermsList = AddExUserPermsSmbToList(pExUserPermsList, pExUserPerms); | ||
321 | pSID = (PSID)(pEA[dwCounter].Trustee.ptstrName); | ||
322 | if (!::LookupAccountSidW(NULL, pSID, pExUserPerms->scau.wzName, &nUserNameSize, pExUserPerms->scau.wzDomain, &nDomainNameSize, &peUse)) | ||
323 | { | ||
324 | hr = E_FAIL; | ||
325 | ExitOnFailure(hr, "Failed to get account name from SID"); | ||
326 | } | ||
327 | pExUserPerms->nPermissions = pEA[dwCounter].grfAccessPermissions; | ||
328 | pExUserPerms->accessMode = pEA[dwCounter].grfAccessMode; | ||
329 | ++dwUserPermsCount; | ||
330 | nUserNameSize = MAX_DARWIN_COLUMN; | ||
331 | nDomainNameSize = MAX_DARWIN_COLUMN; | ||
332 | } | ||
333 | } | ||
334 | *ppExUserPermsList = pExUserPermsList; | ||
335 | *pUserPermsCount = dwUserPermsCount; | ||
336 | |||
337 | LExit: | ||
338 | if (psi) | ||
339 | { | ||
340 | ::NetApiBufferFree(psi); | ||
341 | } | ||
342 | |||
343 | if (pEA) | ||
344 | { | ||
345 | ::LocalFree(pEA); | ||
346 | } | ||
347 | |||
348 | return hr; | ||
349 | } | ||
350 | |||
351 | |||
352 | /******************************************************************** | ||
353 | SchedCreateSmb - schedule one instance of a file share creation | ||
354 | |||
355 | ********************************************************************/ | ||
356 | HRESULT SchedCreateSmb(SCA_SMB* pss) | ||
357 | { | ||
358 | HRESULT hr = S_OK; | ||
359 | |||
360 | WCHAR wzDomainUser[255]; // "domain\user" | ||
361 | SCA_SMB_EX_USER_PERMS* pExUserPermsList = NULL; | ||
362 | int nCounter = 0; | ||
363 | WCHAR* pwzRollbackCustomActionData = NULL; | ||
364 | WCHAR* pwzCustomActionData = NULL; | ||
365 | |||
366 | hr = WcaWriteStringToCaData(pss->wzShareName, &pwzRollbackCustomActionData); | ||
367 | ExitOnFailure(hr, "failed to add ShareName to CustomActionData"); | ||
368 | |||
369 | hr = WcaWriteStringToCaData(pss->wzShareName, &pwzCustomActionData); | ||
370 | ExitOnFailure(hr, "failed to add ShareName to CustomActionData"); | ||
371 | |||
372 | hr = WcaWriteStringToCaData(pss->wzDescription, &pwzCustomActionData); | ||
373 | ExitOnFailure(hr, "Failed to add server name to CustomActionData"); | ||
374 | |||
375 | hr = WcaWriteStringToCaData(pss->wzDirectory, &pwzCustomActionData); | ||
376 | ExitOnFailure(hr, "Failed to add full path instance to CustomActionData"); | ||
377 | |||
378 | hr = WcaWriteStringToCaData(pss->fUseIntegratedAuth ? L"1" : L"0", &pwzCustomActionData); | ||
379 | ExitOnFailure(hr, "Failed to add server name to CustomActionData"); | ||
380 | |||
381 | if (pss->fLegacyUserProvided) | ||
382 | { | ||
383 | hr = WcaWriteIntegerToCaData(pss->nUserPermissionCount + 1, &pwzCustomActionData); | ||
384 | ExitOnFailure(hr, "Failed to add additional user permission count to CustomActionData"); | ||
385 | |||
386 | hr = UserBuildDomainUserName(wzDomainUser, countof(wzDomainUser), pss->scau.wzName, pss->scau.wzDomain); | ||
387 | ExitOnFailure(hr, "Failed to build user and domain name for CustomActionData"); | ||
388 | hr = WcaWriteStringToCaData(wzDomainUser, &pwzCustomActionData); | ||
389 | ExitOnFailure(hr, "Failed to add server Domain\\UserName to CustomActionData"); | ||
390 | |||
391 | hr = WcaWriteIntegerToCaData(pss->nPermissions, &pwzCustomActionData); | ||
392 | ExitOnFailure(hr, "Failed to add permissions to CustomActionData"); | ||
393 | } | ||
394 | else | ||
395 | { | ||
396 | hr = WcaWriteIntegerToCaData(pss->nUserPermissionCount, &pwzCustomActionData); | ||
397 | ExitOnFailure(hr, "Failed to add additional user permission count to CustomActionData"); | ||
398 | } | ||
399 | |||
400 | if (pss->nUserPermissionCount > 0) | ||
401 | { | ||
402 | nCounter = 0; | ||
403 | for (pExUserPermsList = pss->pExUserPerms; pExUserPermsList; pExUserPermsList = pExUserPermsList->pExUserPermsNext) | ||
404 | { | ||
405 | Assert(nCounter < pss->nUserPermissionCount); | ||
406 | |||
407 | hr = UserBuildDomainUserName(wzDomainUser, countof(wzDomainUser), pExUserPermsList->scau.wzName, pExUserPermsList->scau.wzDomain); | ||
408 | ExitOnFailure(hr, "Failed to build user and domain name for CustomActionData"); | ||
409 | hr = WcaWriteStringToCaData(wzDomainUser, &pwzCustomActionData); | ||
410 | ExitOnFailure(hr, "Failed to add server Domain\\UserName to CustomActionData"); | ||
411 | |||
412 | hr = WcaWriteIntegerToCaData((int)pExUserPermsList->accessMode, &pwzCustomActionData); | ||
413 | ExitOnFailure(hr, "Failed to add access mode to CustomActionData"); | ||
414 | |||
415 | hr = WcaWriteIntegerToCaData(pExUserPermsList->nPermissions, &pwzCustomActionData); | ||
416 | ExitOnFailure(hr, "Failed to add permissions to CustomActionData"); | ||
417 | ++nCounter; | ||
418 | } | ||
419 | Assert(nCounter == pss->nUserPermissionCount); | ||
420 | } | ||
421 | |||
422 | // Schedule the rollback first | ||
423 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CreateSmbRollback"), pwzRollbackCustomActionData, COST_SMB_DROPSMB); | ||
424 | ExitOnFailure(hr, "Failed to schedule DropSmb action"); | ||
425 | |||
426 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CreateSmb"), pwzCustomActionData, COST_SMB_CREATESMB); | ||
427 | ExitOnFailure(hr, "Failed to schedule CreateSmb action"); | ||
428 | |||
429 | LExit: | ||
430 | ReleaseStr(pwzRollbackCustomActionData); | ||
431 | ReleaseStr(pwzCustomActionData); | ||
432 | |||
433 | if (pExUserPermsList) | ||
434 | { | ||
435 | ScaExUserPermsSmbFreeList(pExUserPermsList); | ||
436 | } | ||
437 | |||
438 | return hr; | ||
439 | } | ||
440 | |||
441 | |||
442 | /******************************************************************** | ||
443 | ScaSmbInstall - for every file share, schedule the create custom action | ||
444 | |||
445 | ********************************************************************/ | ||
446 | HRESULT ScaSmbInstall(SCA_SMB* pssList) | ||
447 | { | ||
448 | HRESULT hr = S_FALSE; // assume nothing will be done | ||
449 | SCA_SMB* pss = NULL; | ||
450 | |||
451 | for (pss = pssList; pss; pss = pss->pssNext) | ||
452 | { | ||
453 | // if installing this component | ||
454 | if (WcaIsInstalling(pss->isInstalled, pss->isAction) ) | ||
455 | { | ||
456 | hr = SchedCreateSmb(pss); | ||
457 | ExitOnFailure(hr, "Failed to schedule the creation of the fileshare: %ls", pss->wzShareName); | ||
458 | } | ||
459 | } | ||
460 | |||
461 | LExit: | ||
462 | return hr; | ||
463 | } | ||
464 | |||
465 | |||
466 | /******************************************************************** | ||
467 | SchedDropSmb - schedule one instance of a file share removal | ||
468 | |||
469 | ********************************************************************/ | ||
470 | HRESULT SchedDropSmb(SCA_SMB* pss) | ||
471 | { | ||
472 | HRESULT hr = S_OK; | ||
473 | |||
474 | WCHAR* pwzCustomActionData = NULL; | ||
475 | WCHAR* pwzRollbackCustomActionData = NULL; | ||
476 | SCA_SMB_EX_USER_PERMS *pExUserPermsList = NULL; | ||
477 | SCA_SMB_EX_USER_PERMS *pExUserPerm = NULL; | ||
478 | WCHAR wzDomainUser[255]; // "domain\user" | ||
479 | DWORD dwUserPermsCount = 0; | ||
480 | |||
481 | // roll back DropSmb | ||
482 | hr = WcaWriteStringToCaData(pss->wzShareName, &pwzRollbackCustomActionData); | ||
483 | ExitOnFailure(hr, "failed to add ShareName to CustomActionData"); | ||
484 | |||
485 | hr = WcaWriteStringToCaData(pss->wzDescription, &pwzRollbackCustomActionData); | ||
486 | ExitOnFailure(hr, "Failed to add server name to CustomActionData"); | ||
487 | |||
488 | hr = WcaWriteStringToCaData(pss->wzDirectory, &pwzRollbackCustomActionData); | ||
489 | ExitOnFailure(hr, "Failed to add full path instance to CustomActionData"); | ||
490 | |||
491 | hr = WcaWriteStringToCaData(L"1", &pwzRollbackCustomActionData); | ||
492 | ExitOnFailure(hr, "Failed to add useintegrated flag to CustomActionData"); | ||
493 | |||
494 | hr = RetrieveFileShareUserPerm(pss, &pExUserPermsList, &dwUserPermsCount); | ||
495 | ExitOnFailure(hr, "Failed to retrieve SMBShare's user permissions"); | ||
496 | |||
497 | hr = WcaWriteIntegerToCaData((int)dwUserPermsCount, &pwzRollbackCustomActionData); | ||
498 | ExitOnFailure(hr, "Failed to add additional user permission count to CustomActionData"); | ||
499 | |||
500 | for (pExUserPerm = pExUserPermsList; pExUserPerm; pExUserPerm = pExUserPerm->pExUserPermsNext) | ||
501 | { | ||
502 | hr = UserBuildDomainUserName(wzDomainUser, countof(wzDomainUser), pExUserPerm->scau.wzName, pExUserPerm->scau.wzDomain); | ||
503 | ExitOnFailure(hr, "Failed to build user and domain name for CustomActionData"); | ||
504 | hr = WcaWriteStringToCaData(wzDomainUser, &pwzRollbackCustomActionData); | ||
505 | ExitOnFailure(hr, "Failed to add server Domain\\UserName to CustomActionData"); | ||
506 | |||
507 | hr = WcaWriteIntegerToCaData((int)pExUserPerm->accessMode, &pwzRollbackCustomActionData); | ||
508 | ExitOnFailure(hr, "Failed to add access mode to CustomActionData"); | ||
509 | |||
510 | hr = WcaWriteIntegerToCaData(pExUserPerm->nPermissions, &pwzRollbackCustomActionData); | ||
511 | ExitOnFailure(hr, "Failed to add permissions to CustomActionData"); | ||
512 | } | ||
513 | |||
514 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"DropSmbRollback"), pwzRollbackCustomActionData, COST_SMB_CREATESMB); | ||
515 | ExitOnFailure(hr, "Failed to schedule DropSmbRollback action"); | ||
516 | |||
517 | // DropSMB | ||
518 | hr = WcaWriteStringToCaData(pss->wzShareName, &pwzCustomActionData); | ||
519 | ExitOnFailure(hr, "failed to add ShareName to CustomActionData"); | ||
520 | |||
521 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"DropSmb"), pwzCustomActionData, COST_SMB_DROPSMB); | ||
522 | ExitOnFailure(hr, "Failed to schedule DropSmb action"); | ||
523 | |||
524 | LExit: | ||
525 | ReleaseStr(pwzCustomActionData); | ||
526 | |||
527 | if (pExUserPermsList) | ||
528 | { | ||
529 | ScaExUserPermsSmbFreeList(pExUserPermsList); | ||
530 | } | ||
531 | |||
532 | return hr; | ||
533 | |||
534 | } | ||
535 | |||
536 | |||
537 | /******************************************************************** | ||
538 | ScaSmbUninstall - for every file share, schedule the drop custom action | ||
539 | |||
540 | ********************************************************************/ | ||
541 | HRESULT ScaSmbUninstall(SCA_SMB* pssList) | ||
542 | { | ||
543 | HRESULT hr = S_FALSE; // assume nothing will be done | ||
544 | SCA_SMB* pss = NULL; | ||
545 | |||
546 | for (pss = pssList; pss; pss = pss->pssNext) | ||
547 | { | ||
548 | // if uninstalling this component | ||
549 | if (WcaIsUninstalling(pss->isInstalled, pss->isAction) ) | ||
550 | { | ||
551 | hr = SchedDropSmb(pss); | ||
552 | ExitOnFailure(hr, "Failed to remove file share %ls", pss->wzShareName); | ||
553 | } | ||
554 | } | ||
555 | |||
556 | LExit: | ||
557 | return hr; | ||
558 | } | ||
559 | |||
560 | LPCWSTR vcsSmbExUserPermsQuery = L"SELECT `FileShare_`,`User_`,`Permissions` " | ||
561 | L"FROM `Wix4FileSharePermissions` WHERE `FileShare_`=?"; | ||
562 | |||
563 | enum eSmbUserPermsQuery { | ||
564 | ssupqFileShare = 1, | ||
565 | ssupqUser, | ||
566 | ssupqPermissions | ||
567 | |||
568 | }; | ||
569 | |||
570 | |||
571 | /******************************************************************** | ||
572 | ScaSmbExPermsRead - for Every entry in File Permissions table add a | ||
573 | User Name & Permissions structure to the List | ||
574 | |||
575 | ********************************************************************/ | ||
576 | HRESULT ScaSmbExPermsRead(SCA_SMB* pss) | ||
577 | { | ||
578 | HRESULT hr = S_OK; | ||
579 | PMSIHANDLE hView, hRec; | ||
580 | |||
581 | LPWSTR pwzData = NULL; | ||
582 | SCA_SMB_EX_USER_PERMS* pExUserPermsList = pss->pExUserPerms; | ||
583 | SCA_SMB_EX_USER_PERMS* pExUserPerms = NULL; | ||
584 | int nCounter = 0; | ||
585 | |||
586 | hRec = ::MsiCreateRecord(1); | ||
587 | hr = WcaSetRecordString(hRec, 1, pss->wzId); | ||
588 | ExitOnFailure(hr, "Failed to look up FileShare"); | ||
589 | |||
590 | hr = WcaOpenView(vcsSmbExUserPermsQuery, &hView); | ||
591 | ExitOnFailure(hr, "Failed to open view on Wix4FileSharePermissions table"); | ||
592 | hr = WcaExecuteView(hView, hRec); | ||
593 | ExitOnFailure(hr, "Failed to execute view on Wix4FileSharePermissions table"); | ||
594 | |||
595 | // loop through all User/Permissions paris returned | ||
596 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
597 | { | ||
598 | pExUserPerms = NewExUserPermsSmb(); | ||
599 | if (!pExUserPerms) | ||
600 | { | ||
601 | hr = E_OUTOFMEMORY; | ||
602 | break; | ||
603 | } | ||
604 | Assert(pExUserPerms); | ||
605 | ::ZeroMemory(pExUserPerms, sizeof(*pExUserPerms)); | ||
606 | |||
607 | hr = WcaGetRecordString(hRec, ssupqUser, &pwzData); | ||
608 | ExitOnFailure(hr, "Failed to get Wix4FileSharePermissions.User"); | ||
609 | hr = ScaGetUser(pwzData, &pExUserPerms->scau); | ||
610 | ExitOnFailure(hr, "Failed to get user information for fileshare: '%ls'", pss->wzShareName); | ||
611 | |||
612 | hr = WcaGetRecordInteger(hRec, ssupqPermissions, &pExUserPerms->nPermissions); | ||
613 | ExitOnFailure(hr, "Failed to get Wix4FileSharePermissions.Permissions"); | ||
614 | pExUserPerms->accessMode = SET_ACCESS; // we only support SET_ACCESS here | ||
615 | |||
616 | pExUserPermsList = AddExUserPermsSmbToList(pExUserPermsList, pExUserPerms); | ||
617 | ++nCounter; | ||
618 | pExUserPerms = NULL; // set the smb NULL so it doesn't accidentally get freed below | ||
619 | } | ||
620 | |||
621 | if (E_NOMOREITEMS == hr) | ||
622 | { | ||
623 | hr = S_OK; | ||
624 | pss->pExUserPerms = pExUserPermsList; | ||
625 | pss->nUserPermissionCount = nCounter; | ||
626 | } | ||
627 | ExitOnFailure(hr, "Failure occured while processing FileShare table"); | ||
628 | |||
629 | LExit: | ||
630 | // if anything was left over after an error clean it all up | ||
631 | if (pExUserPerms) | ||
632 | { | ||
633 | ScaExUserPermsSmbFreeList(pExUserPerms); | ||
634 | } | ||
635 | |||
636 | ReleaseStr(pwzData); | ||
637 | |||
638 | return hr; | ||
639 | } | ||