WindowsXP-SP1/admin/select/src/downlvl.cxx
2020-09-30 16:53:49 +02:00

285 lines
7.6 KiB
C++

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997 - 2000.
//
// File: downlvl.cxx
//
// Contents: Functions which return information about domains when
// uplevel (Windows 2000 or later) APIs are not available
// (i.e. when joined to an NT4 domain or in a workgroup).
//
// Functions: GetLsaAccountDomainInfo
// GetDomainSid
//
// History: 06-22-2000 DavidMun Created
//
//---------------------------------------------------------------------------
#include "headers.hxx"
#pragma hdrstop
//+--------------------------------------------------------------------------
//
// Function: GetLsaAccountDomainInfo
//
// Synopsis: Use LSA APIs to fill *[ppAccountDomainInfo].
//
// Arguments: [pwzServerName] - target computer
// [phlsaServer] - filled with handle returned by
// LsaOpenPolicy
// [ppAccountDomainInfo] - filled with domain info returned
// by LsaQueryInformationPolicy.
//
// Returns: HRESULT
//
// History: 06-22-2000 DavidMun Created
//
//---------------------------------------------------------------------------
HRESULT
GetLsaAccountDomainInfo(
PCWSTR pwzServerName,
PLSA_HANDLE phlsaServer,
PPOLICY_ACCOUNT_DOMAIN_INFO *ppAccountDomainInfo)
{
TRACE_FUNCTION(GetLsaAccountDomainInfo);
HRESULT hr = S_OK;
NTSTATUS nts = ERROR_SUCCESS;
LSA_OBJECT_ATTRIBUTES oa;
SECURITY_QUALITY_OF_SERVICE sqos;
BOOL fOk;
do
{
//
// Open the lsa policy object on the target server
//
ZeroMemory(&sqos, sizeof sqos);
sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
sqos.ImpersonationLevel = SecurityImpersonation;
sqos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
sqos.EffectiveOnly = FALSE;
ZeroMemory(&oa, sizeof oa);
oa.Length = sizeof oa;
oa.SecurityQualityOfService = &sqos;
UNICODE_STRING uszServerName;
if (pwzServerName)
{
fOk = RtlCreateUnicodeString(&uszServerName, pwzServerName);
if (!fOk)
{
hr = E_OUTOFMEMORY;
DBG_OUT_HRESULT(hr);
break;
}
}
nts = LsaOpenPolicy(pwzServerName ? &uszServerName : NULL,
&oa,
POLICY_VIEW_LOCAL_INFORMATION,
phlsaServer);
if (pwzServerName)
{
RtlFreeUnicodeString(&uszServerName);
}
BREAK_ON_FAIL_NTSTATUS(nts);
//
// Get the domain information for the passed-in server
//
nts = LsaQueryInformationPolicy(*phlsaServer,
PolicyAccountDomainInformation,
(LPVOID *)ppAccountDomainInfo);
BREAK_ON_FAIL_NTSTATUS(nts);
} while (0);
if (NT_ERROR(nts))
{
hr = E_FAIL;
}
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: GetDomainSid
//
// Synopsis: Get the SID of domain with name [pwzDomainName].
//
// Arguments: [pwzDomainName] - name of domain for which to retrieve SID
// [ppSid] - filled with pointer to domain's SID
// [ppwzDC] - if non-NULL, filled with name of DC for
// domain [pwzDomainName].
//
// Returns: HRESULT
//
// History: 06-22-2000 DavidMun Created
//
//---------------------------------------------------------------------------
HRESULT
GetDomainSid(
PWSTR pwzDomainName,
PSID *ppSid,
PWSTR *ppwzDC)
{
Dbg(DEB_TRACE, "GetDomainSid('%ws')\n", pwzDomainName);
HRESULT hr;
ULONG ulResult;
PWSTR pwzPDC = NULL;
NTSTATUS nts;
LSA_HANDLE hlsaServer = NULL;
POLICY_ACCOUNT_DOMAIN_INFO *pAccountDomainInfo = NULL;
SECURITY_QUALITY_OF_SERVICE sqos;
LSA_OBJECT_ATTRIBUTES oa;
BOOL fOk;
do
{
//
// First find a DC in the domain
//
ulResult = NetGetDCName(NULL, pwzDomainName, (LPBYTE *) &pwzPDC);
if (ulResult != ERROR_SUCCESS)
{
hr = E_FAIL;
Dbg(DEB_ERROR, "GetDomainSid: NetGetDCName err=%uL\n", ulResult);
break;
}
Dbg(DEB_TRACE,
"GetDomainSid: DC of domain '%ws' is '%ws'\n",
pwzDomainName,
pwzPDC);
PWSTR pwzDCname = pwzPDC + 2;
if (ppwzDC)
{
*ppwzDC = new WCHAR[lstrlen(pwzDCname) + 1];
if (!*ppwzDC)
{
hr = E_OUTOFMEMORY;
DBG_OUT_HRESULT(hr);
break;
}
lstrcpy(*ppwzDC, pwzDCname);
}
hr = GetLsaAccountDomainInfo(pwzDCname,
&hlsaServer,
&pAccountDomainInfo);
//
// Open the lsa policy object on the DC
//
ZeroMemory(&sqos, sizeof sqos);
sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
sqos.ImpersonationLevel = SecurityImpersonation;
sqos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
sqos.EffectiveOnly = FALSE;
ZeroMemory(&oa, sizeof oa);
oa.Length = sizeof oa;
oa.SecurityQualityOfService = &sqos;
//
// Get a handle to lsa policy for queries about domains
//
UNICODE_STRING uszServerName;
fOk = RtlCreateUnicodeString(&uszServerName, pwzDCname);
if (!fOk)
{
hr = E_OUTOFMEMORY;
DBG_OUT_HRESULT(hr);
break;
}
nts = LsaOpenPolicy(&uszServerName,
&oa,
POLICY_VIEW_LOCAL_INFORMATION,
&hlsaServer);
RtlFreeUnicodeString(&uszServerName);
BREAK_ON_FAIL_NTSTATUS(nts);
//
// Get the SID for the domain
//
nts = LsaQueryInformationPolicy(hlsaServer,
PolicyAccountDomainInformation,
(LPVOID *)&pAccountDomainInfo);
BREAK_ON_FAIL_NTSTATUS(nts);
if (pAccountDomainInfo->DomainSid)
{
ULONG cbSid = GetLengthSid(pAccountDomainInfo->DomainSid);
ASSERT(cbSid);
*ppSid = (PSID) new BYTE[cbSid];
if (!*ppSid)
{
hr = E_OUTOFMEMORY;
DBG_OUT_HRESULT(hr);
break;
}
CopyMemory(*ppSid, pAccountDomainInfo->DomainSid, cbSid);
}
else
{
hr = E_FAIL;
Dbg(DEB_ERROR,
"GetDomainSid: couldn't obtain sid for domain '%ws'\n",
pwzDomainName);
}
} while (0);
//
// Release resources
//
if (hlsaServer)
{
LsaClose(hlsaServer);
}
if (pwzPDC)
{
NetApiBufferFree(pwzPDC);
}
if (pAccountDomainInfo)
{
LsaFreeMemory(pAccountDomainInfo);
}
return hr;
}