From d77dca43e87e8711b19910a8fd49138f939bf0a4 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Tue, 4 May 2021 22:48:58 -0700 Subject: Move Msmq.wixext into ext --- src/ext/Msmq/ca/mqutilexec.cpp | 380 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 380 insertions(+) create mode 100644 src/ext/Msmq/ca/mqutilexec.cpp (limited to 'src/ext/Msmq/ca/mqutilexec.cpp') diff --git a/src/ext/Msmq/ca/mqutilexec.cpp b/src/ext/Msmq/ca/mqutilexec.cpp new file mode 100644 index 00000000..a9c56e02 --- /dev/null +++ b/src/ext/Msmq/ca/mqutilexec.cpp @@ -0,0 +1,380 @@ +// 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. + +#include "precomp.h" + + +// private structs + +struct PCA_WELLKNOWN_SID +{ + LPCWSTR pwzName; + SID_IDENTIFIER_AUTHORITY iaIdentifierAuthority; + BYTE nSubAuthorityCount; + DWORD dwSubAuthority[8]; +}; + + +// well known SIDs + +PCA_WELLKNOWN_SID wsWellKnownSids[] = { + {L"\\Everyone", SECURITY_WORLD_SID_AUTHORITY, 1, {SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0}}, + {L"\\Administrators", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0}}, + {L"\\LocalSystem", SECURITY_NT_AUTHORITY, 1, {SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0}}, + {L"\\LocalService", SECURITY_NT_AUTHORITY, 1, {SECURITY_LOCAL_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0}}, + {L"\\NetworkService", SECURITY_NT_AUTHORITY, 1, {SECURITY_NETWORK_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0}}, + {L"\\AuthenticatedUser", SECURITY_NT_AUTHORITY, 1, {SECURITY_AUTHENTICATED_USER_RID, 0, 0, 0, 0, 0, 0, 0}}, + {L"\\Guests", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS, 0, 0, 0, 0, 0, 0}}, + {L"\\Users", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0}}, + {L"\\CREATOR OWNER", SECURITY_NT_AUTHORITY, 1, {SECURITY_CREATOR_OWNER_RID, 0, 0, 0, 0, 0, 0, 0}}, + {NULL, SECURITY_NULL_SID_AUTHORITY, 0, {0, 0, 0, 0, 0, 0, 0, 0}} +}; + + +// prototypes for private helper functions + +static HRESULT CreateSidFromDomainRidPair( + PSID pDomainSid, + DWORD dwRid, + PSID* ppSid + ); +static HRESULT InitLsaUnicodeString( + PLSA_UNICODE_STRING plusStr, + LPCWSTR pwzStr, + DWORD dwLen + ); +static void FreeLsaUnicodeString( + PLSA_UNICODE_STRING plusStr + ); + + +// function definitions + +HRESULT PcaActionDataMessage( + DWORD cArgs, + ... + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + PMSIHANDLE hRec; + va_list args; + + // record + hRec = ::MsiCreateRecord(cArgs); + ExitOnNull(hRec, hr, E_OUTOFMEMORY, "Failed to create record"); + + va_start(args, cArgs); + for (DWORD i = 1; i <= cArgs; i++) + { + LPCWSTR pwzArg = va_arg(args, WCHAR*); + if (pwzArg && *pwzArg) + { + er = ::MsiRecordSetStringW(hRec, i, pwzArg); + ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set record field string"); + } + } + va_end(args); + + // message + er = WcaProcessMessage(INSTALLMESSAGE_ACTIONDATA, hRec); + if (0 == er || IDOK == er || IDYES == er) + { + hr = S_OK; + } + else if (ERROR_INSTALL_USEREXIT == er || IDABORT == er || IDCANCEL == er) + { + WcaSetReturnValue(ERROR_INSTALL_USEREXIT); // note that the user said exit + hr = S_FALSE; + } + else + hr = E_UNEXPECTED; + +LExit: + return hr; +} + +HRESULT PcaAccountNameToSid( + LPCWSTR pwzAccountName, + PSID* ppSid + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + NTSTATUS st = 0; + + PSID pSid = NULL; + LSA_OBJECT_ATTRIBUTES loaAttributes; + LSA_HANDLE lsahPolicy = NULL; + LSA_UNICODE_STRING lusName; + PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL; + PLSA_TRANSLATED_SID pltsSid = NULL; + + ::ZeroMemory(&loaAttributes, sizeof(loaAttributes)); + ::ZeroMemory(&lusName, sizeof(lusName)); + + // identify well known SIDs + for (PCA_WELLKNOWN_SID* pWS = wsWellKnownSids; pWS->pwzName; pWS++) + { + if (0 == lstrcmpiW(pwzAccountName, pWS->pwzName)) + { + // allocate SID buffer + pSid = (PSID)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, ::GetSidLengthRequired(pWS->nSubAuthorityCount)); + ExitOnNull(pSid, hr, E_OUTOFMEMORY, "Failed to allocate buffer for SID"); + + // initialize SID + ::InitializeSid(pSid, &pWS->iaIdentifierAuthority, pWS->nSubAuthorityCount); + + // copy sub autorities + for (DWORD i = 0; i < pWS->nSubAuthorityCount; i++) + *::GetSidSubAuthority(pSid, i) = pWS->dwSubAuthority[i]; + + break; + } + } + + // lookup name + if (!pSid) + { + // open policy handle + st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy); + er = ::LsaNtStatusToWinError(st); + ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle"); + + // create account name lsa unicode string + hr = InitLsaUnicodeString(&lusName, pwzAccountName, wcslen(pwzAccountName)); + ExitOnFailure(hr, "Failed to initialize account name string"); + + // lookup name + st = ::LsaLookupNames(lsahPolicy, 1, &lusName, &plrdsDomains, &pltsSid); + er = ::LsaNtStatusToWinError(st); + ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to lookup account names"); + + if (SidTypeDomain == pltsSid->Use) + ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Domain SIDs not supported"); + + // convert sid + hr = CreateSidFromDomainRidPair(plrdsDomains->Domains[pltsSid->DomainIndex].Sid, pltsSid->RelativeId, &pSid); + ExitOnFailure(hr, "Failed to convert SID"); + } + + *ppSid = pSid; + pSid = NULL; + + hr = S_OK; + +LExit: + // clean up + if (pSid) + ::HeapFree(::GetProcessHeap(), 0, pSid); + if (lsahPolicy) + ::LsaClose(lsahPolicy); + if (plrdsDomains) + ::LsaFreeMemory(plrdsDomains); + if (pltsSid) + ::LsaFreeMemory(pltsSid); + FreeLsaUnicodeString(&lusName); + + return hr; +} + +HRESULT PcaSidToAccountName( + PSID pSid, + LPWSTR* ppwzAccountName + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + NTSTATUS st = 0; + + LSA_OBJECT_ATTRIBUTES loaAttributes; + LSA_HANDLE lsahPolicy = NULL; + PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL; + PLSA_TRANSLATED_NAME pltnName = NULL; + + LPWSTR pwzDomain = NULL; + LPWSTR pwzName = NULL; + + ::ZeroMemory(&loaAttributes, sizeof(loaAttributes)); + + // open policy handle + st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy); + er = ::LsaNtStatusToWinError(st); + ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle"); + + // lookup SID + st = ::LsaLookupSids(lsahPolicy, 1, &pSid, &plrdsDomains, &pltnName); + er = ::LsaNtStatusToWinError(st); + ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to lookup SID"); + + if (SidTypeDomain == pltnName->Use) + ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Domain SIDs not supported"); + + // format account name string + if (SidTypeWellKnownGroup != pltnName->Use) + { + PLSA_UNICODE_STRING plusDomain = &plrdsDomains->Domains[pltnName->DomainIndex].Name; + hr = StrAllocString(&pwzDomain, plusDomain->Buffer, plusDomain->Length / sizeof(WCHAR)); + ExitOnFailure(hr, "Failed to allocate name string"); + } + + hr = StrAllocString(&pwzName, pltnName->Name.Buffer, pltnName->Name.Length / sizeof(WCHAR)); + ExitOnFailure(hr, "Failed to allocate domain string"); + + hr = StrAllocFormatted(ppwzAccountName, L"%s\\%s", pwzDomain ? pwzDomain : L"", pwzName); + ExitOnFailure(hr, "Failed to format account name string"); + + hr = S_OK; + +LExit: + // clean up + if (lsahPolicy) + ::LsaClose(lsahPolicy); + if (plrdsDomains) + ::LsaFreeMemory(plrdsDomains); + if (pltnName) + ::LsaFreeMemory(pltnName); + + ReleaseStr(pwzDomain); + ReleaseStr(pwzName); + + return hr; +} + +HRESULT PcaBuildAccountName( + LPCWSTR pwzDomain, + LPCWSTR pwzName, + LPWSTR* ppwzAccount + ) +{ + HRESULT hr = S_OK; + + WCHAR wzComputerName[MAX_COMPUTERNAME_LENGTH + 1]; + ::ZeroMemory(wzComputerName, sizeof(wzComputerName)); + + // if domain is '.', get computer name + if (0 == lstrcmpW(pwzDomain, L".")) + { + DWORD dwSize = countof(wzComputerName); + if (!::GetComputerNameW(wzComputerName, &dwSize)) + ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to get computer name"); + } + + // build account name + hr = StrAllocFormatted(ppwzAccount, L"%s\\%s", *wzComputerName ? wzComputerName : pwzDomain, pwzName); + ExitOnFailure(hr, "Failed to build domain user name"); + + hr = S_OK; + +LExit: + return hr; +} + +HRESULT PcaGuidFromString( + LPCWSTR pwzGuid, + LPGUID pGuid + ) +{ + HRESULT hr = S_OK; + + int cch = 0; + + WCHAR wz[39]; + ::ZeroMemory(wz, sizeof(wz)); + + cch = lstrlenW(pwzGuid); + + if (38 == cch && L'{' == pwzGuid[0] && L'}' == pwzGuid[37]) + StringCchCopyW(wz, countof(wz), pwzGuid); + else if (36 == cch) + StringCchPrintfW(wz, countof(wz), L"{%s}", pwzGuid); + else + ExitFunction1(hr = E_INVALIDARG); + + hr = ::CLSIDFromString(wz, pGuid); + +LExit: + return hr; +} + + +// helper function definitions + +static HRESULT CreateSidFromDomainRidPair( + PSID pDomainSid, + DWORD dwRid, + PSID* ppSid + ) +{ + HRESULT hr = S_OK; + + PSID pSid = NULL; + + // get domain SID sub authority count + UCHAR ucSubAuthorityCount = *::GetSidSubAuthorityCount(pDomainSid); + + // allocate SID buffer + DWORD dwLengthRequired = ::GetSidLengthRequired(ucSubAuthorityCount + (UCHAR)1); + if (*ppSid) + { + SIZE_T ccb = ::HeapSize(::GetProcessHeap(), 0, *ppSid); + if (-1 == ccb) + ExitOnFailure(hr = E_FAIL, "Failed to get size of SID buffer"); + + if (ccb < dwLengthRequired) + { + pSid = (PSID)::HeapReAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, *ppSid, dwLengthRequired); + ExitOnNull(pSid, hr, E_OUTOFMEMORY, "Failed to reallocate buffer for SID, len: %d", dwLengthRequired); + *ppSid = pSid; + } + } + else + { + *ppSid = (PSID)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, dwLengthRequired); + ExitOnNull(*ppSid, hr, E_OUTOFMEMORY, "Failed to allocate buffer for SID, len: %d", dwLengthRequired); + } + + ::InitializeSid(*ppSid, ::GetSidIdentifierAuthority(pDomainSid), ucSubAuthorityCount + (UCHAR)1); + + // copy sub autorities + DWORD i = 0; + for (; i < ucSubAuthorityCount; i++) + *::GetSidSubAuthority(*ppSid, i) = *::GetSidSubAuthority(pDomainSid, i); + *::GetSidSubAuthority(*ppSid, i) = dwRid; + + hr = S_OK; + +LExit: + return hr; +} + +static HRESULT InitLsaUnicodeString( + PLSA_UNICODE_STRING plusStr, + LPCWSTR pwzStr, + DWORD dwLen + ) +{ + HRESULT hr = S_OK; + + plusStr->Length = (USHORT)dwLen * sizeof(WCHAR); + plusStr->MaximumLength = (USHORT)(dwLen + 1) * sizeof(WCHAR); + + plusStr->Buffer = (WCHAR*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR) * (dwLen + 1)); + ExitOnNull(plusStr->Buffer, hr, E_OUTOFMEMORY, "Failed to allocate account name string"); + + hr = StringCchCopyW(plusStr->Buffer, dwLen + 1, pwzStr); + ExitOnFailure(hr, "Failed to copy buffer"); + + hr = S_OK; + +LExit: + return hr; +} + +static void FreeLsaUnicodeString( + PLSA_UNICODE_STRING plusStr + ) +{ + if (plusStr->Buffer) + ::HeapFree(::GetProcessHeap(), 0, plusStr->Buffer); +} -- cgit v1.2.3-55-g6feb