windows-nt/Source/XPSP1/NT/admin/wizards/addusrw/trstlist.cpp
2020-09-26 16:20:57 +08:00

415 lines
9.7 KiB
C++

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
disptrus.c(pp)
Author:
Scott Field (sfield) 16-Mar-96
Revision:
JonY 16-Apr-96 Modified to .cpp
--*/
#include "stdafx.h"
#include "trstlist.h"
#define RTN_OK 0
#define RTN_ERROR 13
//
// if you have the ddk, include ntstatus.h
//
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_MORE_ENTRIES ((NTSTATUS)0x00000105L)
#define STATUS_NO_MORE_ENTRIES ((NTSTATUS)0x8000001AL)
#endif
#define ELEMENT_COUNT 64 // number of array elements to allocate
CTrustList::CTrustList()
{
m_dwTrustCount = 0;
m_ppszTrustList = (LPWSTR *)HeapAlloc(
GetProcessHeap(), HEAP_ZERO_MEMORY,
ELEMENT_COUNT * sizeof(LPWSTR)
);
}
CTrustList::~CTrustList()
{
//
// free trust list
//
unsigned int i;
for(i = 0 ; i < m_dwTrustCount ; i++) {
if(m_ppszTrustList[i] != NULL)
HeapFree(GetProcessHeap(), 0, m_ppszTrustList[i]);
}
HeapFree(GetProcessHeap(), 0, m_ppszTrustList);
}
BOOL
CTrustList::BuildTrustList(
LPTSTR Target
)
{
LSA_HANDLE PolicyHandle;
NTSTATUS Status;
PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomain;
BOOL bDC;
NET_API_STATUS nas = NERR_Success; // assume success
BOOL bSuccess = FALSE; // assume this function will fail
//
// open the policy on the specified machine
//
Status = OpenPolicy(
Target,
POLICY_VIEW_LOCAL_INFORMATION,
&PolicyHandle
);
if(Status != STATUS_SUCCESS) {
SetLastError( LsaNtStatusToWinError(Status) );
return FALSE;
}
//
// obtain the AccountDomain, which is common to all three cases
//
Status = LsaQueryInformationPolicy(
PolicyHandle,
PolicyAccountDomainInformation,
(LPVOID*)&AccountDomain
);
if(Status != STATUS_SUCCESS)
goto cleanup;
//
// Note: AccountDomain->DomainSid will contain binary Sid
//
AddTrustToList(&AccountDomain->DomainName);
//
// free memory allocated for account domain
//
LsaFreeMemory(AccountDomain);
//
// find out if the target machine is a domain controller
//
if(!IsDomainController(Target, &bDC)) {
////
goto cleanup;
}
if(!bDC) {
PPOLICY_PRIMARY_DOMAIN_INFO PrimaryDomain;
TCHAR* szPrimaryDomainName = NULL;
TCHAR* DomainController = NULL;
//
// get the primary domain
//
Status = LsaQueryInformationPolicy(
PolicyHandle,
PolicyPrimaryDomainInformation,
(LPVOID*)&PrimaryDomain
);
if(Status != STATUS_SUCCESS)
goto cleanup;
//
// if the primary domain Sid is NULL, we are a non-member, and
// our work is done.
//
if(PrimaryDomain->Sid == NULL) {
LsaFreeMemory(PrimaryDomain);
bSuccess = TRUE;
goto cleanup;
}
AddTrustToList(&PrimaryDomain->Name);
//
// build a copy of what we just added. This is necessary in order
// to lookup the domain controller for the specified domain.
// the Domain name must be NULL terminated for NetGetDCName(),
// and the LSA_UNICODE_STRING buffer is not necessarilly NULL
// terminated. Note that in a practical implementation, we
// could just extract the element we added, since it ends up
// NULL terminated.
//
szPrimaryDomainName = (LPTSTR)HeapAlloc(
GetProcessHeap(), 0,
PrimaryDomain->Name.Length + sizeof(WCHAR) // existing length + NULL
);
if(szPrimaryDomainName != NULL) {
//
// copy the existing buffer to the new storage, appending a NULL
//
_tcsncpy(
szPrimaryDomainName,
PrimaryDomain->Name.Buffer,
(PrimaryDomain->Name.Length / 2) + 1
);
}
LsaFreeMemory(PrimaryDomain);
if(szPrimaryDomainName == NULL) goto cleanup;
//
// get the primary domain controller computer name
//
nas = NetGetDCName(
NULL,
szPrimaryDomainName,
(LPBYTE *)&DomainController
);
HeapFree(GetProcessHeap(), 0, szPrimaryDomainName);
if(nas != NERR_Success)
goto cleanup;
//
// close the policy handle, because we don't need it anymore
// for the workstation case, as we open a handle to a DC
// policy below
//
LsaClose(PolicyHandle);
PolicyHandle = INVALID_HANDLE_VALUE; // invalidate handle value
//
// open the policy on the domain controller
//
Status = OpenPolicy(
DomainController,
POLICY_VIEW_LOCAL_INFORMATION,
&PolicyHandle
);
//
// free the domaincontroller buffer
//
NetApiBufferFree(DomainController);
if(Status != STATUS_SUCCESS)
goto cleanup;
}
//
// build additional trusted domain(s) list and indicate if successful
//
bSuccess = EnumTrustedDomains(PolicyHandle);
cleanup:
//
// close the policy handle
//
if(PolicyHandle != INVALID_HANDLE_VALUE)
LsaClose(PolicyHandle);
if(!bSuccess) {
if(Status != STATUS_SUCCESS)
SetLastError( LsaNtStatusToWinError(Status) );
else if(nas != NERR_Success)
SetLastError( nas );
}
return bSuccess;
}
BOOL
CTrustList::EnumTrustedDomains(
LSA_HANDLE PolicyHandle
)
{
LSA_ENUMERATION_HANDLE lsaEnumHandle=0; // start an enum
PLSA_TRUST_INFORMATION TrustInfo;
ULONG ulReturned; // number of items returned
ULONG ulCounter; // counter for items returned
NTSTATUS Status;
do {
Status = LsaEnumerateTrustedDomains(
PolicyHandle, // open policy handle
&lsaEnumHandle, // enumeration tracker
(LPVOID*)&TrustInfo, // buffer to receive data
32000, // recommended buffer size
&ulReturned // number of items returned
);
//
// get out if an error occurred
//
if( (Status != STATUS_SUCCESS) &&
(Status != STATUS_MORE_ENTRIES) &&
(Status != STATUS_NO_MORE_ENTRIES)
) {
SetLastError( LsaNtStatusToWinError(Status) );
return FALSE;
}
//
// Display results
// Note: Sids are in TrustInfo[ulCounter].Sid
//
for(ulCounter = 0 ; ulCounter < ulReturned ; ulCounter++)
AddTrustToList(&TrustInfo[ulCounter].Name);
//
// free the buffer
//
LsaFreeMemory(TrustInfo);
} while (Status != STATUS_NO_MORE_ENTRIES);
return TRUE;
}
BOOL
CTrustList::IsDomainController(
LPTSTR Server,
LPBOOL bDomainController
)
{
PSERVER_INFO_101 si101;
NET_API_STATUS nas;
nas = NetServerGetInfo(
Server,
101, // info-level
(LPBYTE *)&si101
);
if(nas != NERR_Success) {
SetLastError(nas);
return FALSE;
}
if( (si101->sv101_type & SV_TYPE_DOMAIN_CTRL) ||
(si101->sv101_type & SV_TYPE_DOMAIN_BAKCTRL) ) {
//
// we are dealing with a DC
//
*bDomainController = TRUE;
} else {
*bDomainController = FALSE;
}
NetApiBufferFree(si101);
return TRUE;
}
BOOL
CTrustList::AddTrustToList(
PLSA_UNICODE_STRING UnicodeString
)
{
if(m_dwTrustCount > ELEMENT_COUNT) return FALSE;
//
// allocate storage for array element
//
m_ppszTrustList[m_dwTrustCount] = (LPWSTR)HeapAlloc(
GetProcessHeap(), 0,
UnicodeString->Length + sizeof(WCHAR) // existing length + NULL
);
if(m_ppszTrustList[m_dwTrustCount] == NULL) return FALSE;
//
// copy the existing buffer to the new storage, appending a NULL
//
lstrcpynW(
m_ppszTrustList[m_dwTrustCount],
UnicodeString->Buffer,
(UnicodeString->Length / 2) + 1
);
m_dwTrustCount++; // increment the trust count
return TRUE;
}
void
CTrustList::InitLsaString(
PLSA_UNICODE_STRING LsaString,
LPTSTR String
)
{
DWORD StringLength;
if (String == NULL) {
LsaString->Buffer = NULL;
LsaString->Length = 0;
LsaString->MaximumLength = 0;
return;
}
StringLength = _tcslen(String);
LsaString->Buffer = String;
LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
LsaString->MaximumLength = (USHORT) (StringLength + 1) * sizeof(WCHAR);
}
NTSTATUS
CTrustList::OpenPolicy(
LPTSTR ServerName,
DWORD DesiredAccess,
PLSA_HANDLE PolicyHandle
)
{
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
LSA_UNICODE_STRING ServerString;
PLSA_UNICODE_STRING Server;
//
// Always initialize the object attributes to all zeroes
//
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
if(ServerName != NULL) {
//
// Make a LSA_UNICODE_STRING out of the LPWSTR passed in
//
InitLsaString(&ServerString, ServerName);
Server = &ServerString;
} else {
Server = NULL;
}
//
// Attempt to open the policy
//
return LsaOpenPolicy(
Server,
&ObjectAttributes,
DesiredAccess,
PolicyHandle
);
}