//+-------------------------------------------------------------------------- // // 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; }