WindowsXP-SP1/base/fs/remotefs/dfs/dfsserver/serverlibrary/domaincontrollersupport.cxx
2020-09-30 16:53:49 +02:00

434 lines
13 KiB
C++

#include "DfsGeneric.hxx"
#include "dsgetdc.h"
#include "dsrole.h"
#include "DfsDomainInformation.hxx"
#include "DfsTrustedDomain.hxx"
#include "DfsReferralData.hxx"
#include "DomainControllerSupport.hxx"
#include "DfsReplica.hxx"
#include "dfsadsiapi.hxx"
#include "lmdfs.h"
#include "dfserror.hxx"
#include "dfsfilterapi.hxx"
#define RemoteServerNameString L"remoteServerName"
extern
DFS_SERVER_GLOBAL_DATA DfsServerGlobalData;
#define HRESULT_TO_DFSSTATUS(_x) (_x)
DFSSTATUS
DfsDcInit(
PBOOLEAN pIsDc,
DfsDomainInformation **ppDomainInfo )
{
PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pPrimaryDomainInfo = NULL;
DFSSTATUS Status = ERROR_SUCCESS;
Status = DsRoleGetPrimaryDomainInformation( NULL,
DsRolePrimaryDomainInfoBasic,
(PBYTE *)&pPrimaryDomainInfo);
if (Status == ERROR_SUCCESS)
{
if(pPrimaryDomainInfo->MachineRole == DsRole_RoleStandaloneServer)
{
DfsServerGlobalData.IsWorkGroup = TRUE;
}
else
{
DfsServerGlobalData.IsWorkGroup = FALSE;
}
#if defined(TESTING)
pPrimaryDomainInfo->MachineRole = DsRole_RoleBackupDomainController;
#endif
if ( (pPrimaryDomainInfo->MachineRole == DsRole_RoleBackupDomainController) ||
(pPrimaryDomainInfo->MachineRole == DsRole_RolePrimaryDomainController) )
{
*pIsDc = TRUE;
DfsDomainInformation *pNewDomainInfo = new DfsDomainInformation( &Status );
if (pNewDomainInfo == NULL)
{
Status = ERROR_NOT_ENOUGH_MEMORY;
}
else if (Status != ERROR_SUCCESS)
{
pNewDomainInfo->ReleaseReference();
}
if (Status == ERROR_SUCCESS)
{
*ppDomainInfo = pNewDomainInfo;
}
}
DfsSetDomainNameFlat( pPrimaryDomainInfo->DomainNameFlat);
DfsSetDomainNameDns( pPrimaryDomainInfo->DomainNameDns);
DsRoleFreeMemory(pPrimaryDomainInfo);
}
return Status;
}
//+-------------------------------------------------------------------------
//
// Function: DfsGenerateReferralDataFromRemoteServerNames
// IADs *pObject - the object
// DfsfolderReferralData *pReferralData - the referral data
//
//
// Returns: Status: Success or Error status code
//
// Description: This routine reads the remote server name
// attribute and creates a referral data structure
// so that we can pass a referral based on these names.
//
//--------------------------------------------------------------------------
DFSSTATUS
DfsGenerateReferralDataFromRemoteServerNames(
LPWSTR RootName,
DfsReferralData **ppReferralData )
{
HRESULT HResult = S_OK;
DfsReplica *pReplicas = NULL;
DFSSTATUS Status = ERROR_SUCCESS;
DfsReferralData *pReferralData = NULL;
IADs *pObject = NULL;
VARIANT Variant;
Status = DfsGetDfsRootADObject(NULL,
RootName,
&pObject );
if (Status == ERROR_SUCCESS)
{
pReferralData = new DfsReferralData (&Status );
if (pReferralData == NULL)
{
Status = ERROR_NOT_ENOUGH_MEMORY;
}
else if (Status != ERROR_SUCCESS)
{
pReferralData->ReleaseReference();
}
if (Status == ERROR_SUCCESS)
{
LONG StartNdx, LastNdx;
SAFEARRAY *PropertyArray;
VariantInit( &Variant );
pReferralData->Timeout = DFS_DEFAULT_REFERRAL_TIMEOUT;
HResult = pObject->GetEx( RemoteServerNameString, &Variant );
if ( SUCCEEDED(HResult) )
{
PropertyArray = V_ARRAY( &Variant );
HResult = SafeArrayGetLBound( PropertyArray, 1, &StartNdx );
if ( SUCCEEDED(HResult) )
{
HResult = SafeArrayGetUBound( PropertyArray, 1, &LastNdx );
}
}
if ( SUCCEEDED(HResult) &&
(LastNdx > StartNdx) )
{
VARIANT VariantItem;
pReplicas = new DfsReplica [ LastNdx - StartNdx ];
if (pReplicas != NULL)
{
VariantInit( &VariantItem );
for ( LONG Index = StartNdx; Index < LastNdx; Index++ )
{
HResult = SafeArrayGetElement( PropertyArray,
&Index,
&VariantItem );
if ( SUCCEEDED(HResult) )
{
UNICODE_STRING ServerName, Remaining, Replica;
LPWSTR ReplicaString = V_BSTR( &VariantItem );
RtlInitUnicodeString( &Replica, ReplicaString );
DfsGetFirstComponent( &Replica,
&ServerName,
&Remaining );
Status = (&pReplicas[ Index - StartNdx])->SetTargetServer( &ServerName );
if (Status == ERROR_SUCCESS)
{
Status = (&pReplicas[ Index - StartNdx])->SetTargetFolder( &Remaining );
}
}
else {
Status = DfsGetErrorFromHr( HResult );
}
VariantClear( &VariantItem );
if (Status != ERROR_SUCCESS)
{
delete [] pReplicas;
pReplicas = NULL;
break;
}
}
}
else
{
Status = ERROR_NOT_ENOUGH_MEMORY;
}
}
else
{
Status = DfsGetErrorFromHr( HResult );
}
VariantClear( &Variant );
if (Status == ERROR_SUCCESS)
{
pReferralData->ReplicaCount = LastNdx - StartNdx;
pReferralData->pReplicas = pReplicas;
*ppReferralData = pReferralData;
}
if (Status != ERROR_SUCCESS)
{
pReferralData->ReleaseReference();
}
}
pObject->Release();
}
return Status;
}
//+-------------------------------------------------------------------------
//
// Function: DfsUpdateRemoteServerName
//
// Arguments:
// IADs *pObject - the ds object of interest.
// LPWSTR ServerName - the server name to add or delete
// LPWSTR RemainingName - the rest of the name
// BOOLEAN Add - true for add, false for delete.
//
// Returns: Status: Success or Error status code
//
// Description: This routine updates the RemoteServerName attribute
// in the DS object, either adding a \\servername\remaining
// to the existing DS attribute or removing it, depending
// on add/delete.
// The caller must make sure this parameter does not
// already exist in the add case, or that the parameter
// to be deleted does exist in the delete case.
//
//--------------------------------------------------------------------------
DFSSTATUS
DfsUpdateRemoteServerName(
IADs *pObject,
LPWSTR ServerName,
LPWSTR RemainingName,
BOOLEAN Add )
{
HRESULT HResult = S_OK;
DFSSTATUS Status = ERROR_SUCCESS;
VARIANT Variant;
UNICODE_STRING UpdateName;
LPWSTR pServers[1];
//
// create a unc path using the server and remaining name
// to get a path of type \\servername\remainingname
//
Status = DfsCreateUnicodePathString( &UpdateName,
2, // unc path: 2 leading seperators,
ServerName,
RemainingName);
pServers[0] = UpdateName.Buffer;
if (Status == ERROR_SUCCESS)
{
//
// initialize the variant.
//
VariantInit( &Variant );
//
// Create the variant array with a single entry in it.
//
HResult = ADsBuildVarArrayStr( pServers,
1,
&Variant );
if ( SUCCEEDED(HResult) )
{
//
// either append or delete this string from the remote server
// name attribute
//
HResult = pObject->PutEx( (Add ? ADS_PROPERTY_APPEND : ADS_PROPERTY_DELETE),
RemoteServerNameString,
Variant );
if ( SUCCEEDED(HResult) )
{
//
// now update the object in the DS with this info.
//
HResult = pObject->SetInfo();
}
//
// clear the variant
//
VariantClear( &Variant );
}
if ( SUCCEEDED(HResult) == FALSE)
{
Status = DfsGetErrorFromHr( HResult );
}
//
// free the unicode string we created earlier on.
//
DfsFreeUnicodeString( &UpdateName );
}
return Status;
}
DFSSTATUS
DfsDcEnumerateRoots(
LPWSTR DfsName,
LPBYTE pBuffer,
ULONG BufferSize,
PULONG pEntriesRead,
PULONG pSizeRequired )
{
DFSSTATUS Status = ERROR_SUCCESS;
ULONG_PTR CurrentBuffer = (ULONG_PTR)pBuffer;
ULONG CurrentSize = BufferSize;
UNREFERENCED_PARAMETER(DfsName);
Status = DfsEnumerateDfsADRoots( NULL,
&CurrentBuffer,
&CurrentSize,
pEntriesRead,
pSizeRequired );
return Status;
}
DFSSTATUS
DfsUpdateRootRemoteServerName(
LPWSTR Root,
LPWSTR DCName,
LPWSTR ServerName,
LPWSTR RemainingName,
BOOLEAN Add )
{
IADs *pRootObject = NULL;
DFSSTATUS Status = ERROR_SUCCESS;
Status = DfsGetDfsRootADObject( DCName,
Root,
&pRootObject );
if (Status == ERROR_SUCCESS)
{
Status = DfsUpdateRemoteServerName( pRootObject,
ServerName,
RemainingName,
Add );
pRootObject->Release();
}
return Status;
}
#define UNICODE_STRING_STRUCT(s) \
{sizeof(s) - sizeof(WCHAR), sizeof(s) - sizeof(WCHAR), (s)}
static UNICODE_STRING DfsSpecialDCShares[] = {
UNICODE_STRING_STRUCT(L"SYSVOL"),
UNICODE_STRING_STRUCT(L"NETLOGON"),
};
BOOLEAN
DfsIsSpecialDomainShare(
PUNICODE_STRING pShareName )
{
ULONG Index;
ULONG TotalShares;
BOOLEAN SpecialShare = FALSE;
TotalShares = sizeof(DfsSpecialDCShares) / sizeof(DfsSpecialDCShares[0]);
for (Index = 0; Index < TotalShares; Index++ )
{
if (DfsSpecialDCShares[Index].Length == pShareName->Length) {
if (_wcsnicmp(DfsSpecialDCShares[Index].Buffer,
pShareName->Buffer,
pShareName->Length/sizeof(WCHAR)) == 0)
{
SpecialShare = TRUE;
break;
}
}
}
return SpecialShare;
}
DFSSTATUS
DfsInitializeSpecialDCShares()
{
ULONG Index;
ULONG TotalShares;
DFSSTATUS Status = ERROR_SUCCESS;
TotalShares = sizeof(DfsSpecialDCShares) / sizeof(DfsSpecialDCShares[0]);
for (Index = 0; Index < TotalShares; Index++ )
{
Status = DfsUserModeAttachToFilesystem( &DfsSpecialDCShares[Index],
&DfsSpecialDCShares[Index] );
if (Status != ERROR_SUCCESS)
{
break;
}
}
return Status;
}