windows-nt/Source/XPSP1/NT/base/fs/dfs/dfssvc/dfsipc.c
2020-09-26 16:20:57 +08:00

1146 lines
29 KiB
C

//+----------------------------------------------------------------------------
//
// Copyright (C) 1996, Microsoft Corporation
//
// File: dfsipc.c
//
// Contents: Code to communicate with the Dfs driver. The Dfs driver
// sends messages to the user level to resolve a name to either a domain or
// computer based Dfs name.
//
// Classes: None
//
// History: Feb 1, 1996 Milans Created
//
//-----------------------------------------------------------------------------
#include <ntos.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <dfsfsctl.h>
#include <windows.h>
#include <dfsstr.h>
#include <nodetype.h>
#include <libsup.h>
#include <dfsmrshl.h>
#include <upkt.h>
#include <ntlsa.h>
#include <dfsmsrv.h>
#include <lm.h>
#include <dsrole.h>
#include <crypt.h>
#include <samrpc.h>
#include <logonmsv.h>
#include <dsgetdc.h>
#include <ntdsapi.h>
#include <winldap.h>
#include "dominfo.h"
#include "dfsipc.h"
#include "svcwml.h"
DWORD
DfsLoadSiteTableFromDs(
PLDAP pLDAP,
LPWSTR wszFtDfsName,
ULONG Count,
PUNICODE_STRING pustr);
DWORD
DfsCreateSpcArg(
LPWSTR DomainName,
ULONG Timeout,
ULONG Flags,
ULONG TrustDirection,
ULONG TrustType,
LONG NameCount,
PUNICODE_STRING pustrDCNames,
PDFS_CREATE_SPECIAL_INFO_ARG *ppSpcArg,
PULONG pSize);
DWORD
DfsCreateSiteArg(
LPWSTR ServerName,
ULONG SiteCount,
PUNICODE_STRING pustrSiteNames,
PDFS_CREATE_SITE_INFO_ARG *ppSiteArg,
PULONG pSize);
DWORD
DfsGetFtServersFromDs(
PLDAP pLdap,
LPWSTR wszDomainName,
LPWSTR wszDfsName,
LPWSTR **List);
//
// Event logging and debugging globals
//
extern ULONG DfsSvcVerbose;
extern ULONG DfsEventLog;
extern DFS_DOMAIN_INFO DfsDomainInfo;
extern DSROLE_MACHINE_ROLE DfsMachineRole;
extern WCHAR MachineName[MAX_PATH];
extern WCHAR DomainName[MAX_PATH];
extern WCHAR DomainNameDns[MAX_PATH];
extern WCHAR LastMachineName[MAX_PATH];
extern WCHAR LastDomainName[MAX_PATH];
extern WCHAR SiteName[MAX_PATH];
extern PLDAP pLdap;
extern CRITICAL_SECTION DomListCritSection;
BOOLEAN
DfsGetNextDomainName(
LPWSTR DomName,
ULONG Size);
NTSTATUS
DfsInitOurDomainDCs(VOID)
{
DWORD dwErr;
LPWSTR OurSite;
NTSTATUS status;
HANDLE dfsHandle = NULL;
IO_STATUS_BLOCK ioStatus;
ULONG cDom;
PDFS_CREATE_SPECIAL_INFO_ARG pSpcArg;
ULONG Size;
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfsInitOurDomainDCs()\n");
#endif
dwErr = DsGetSiteName(
NULL,
&OurSite);
RtlZeroMemory(SiteName, MAX_PATH * sizeof(WCHAR));
if (dwErr == NO_ERROR) {
wcscpy(SiteName, OurSite);
NetApiBufferFree(OurSite);
}
status = DfsOpen(&dfsHandle, NULL);
if (NT_SUCCESS(status)) {
#if DBG
if (DfsSvcVerbose)
DbgPrint("Domain %ws/%ws\n",
DomainName,
DomainNameDns);
#endif
status = DfsCreateSpcArg(
DomainName,
0,
DFS_SPECIAL_INFO_NETBIOS,
TRUST_DIRECTION_BIDIRECTIONAL,
TRUST_TYPE_UPLEVEL,
-1,
NULL,
&pSpcArg,
&Size);
if (status == ERROR_SUCCESS) {
status = NtFsControlFile(
dfsHandle,
NULL, // Event,
NULL, // ApcRoutine,
NULL, // ApcContext,
&ioStatus,
FSCTL_DFS_CREATE_SPECIAL_INFO,
pSpcArg,
Size,
NULL,
0);
free(pSpcArg);
}
status = DfsCreateSpcArg(
DomainNameDns,
0,
0,
TRUST_DIRECTION_BIDIRECTIONAL,
TRUST_TYPE_UPLEVEL,
-1,
NULL,
&pSpcArg,
&Size);
if (status == ERROR_SUCCESS) {
status = NtFsControlFile(
dfsHandle,
NULL, // Event,
NULL, // ApcRoutine,
NULL, // ApcContext,
&ioStatus,
FSCTL_DFS_CREATE_SPECIAL_INFO,
pSpcArg,
Size,
NULL,
0);
#if DBG
if (DfsSvcVerbose)
DbgPrint("NtFsControlFile(FSCTL_DFS_CREATE_SPECIAL_INFO) returned 0x%x\n",
status);
#endif
free(pSpcArg);
}
}
if (dfsHandle != NULL) {
NtClose( dfsHandle);
}
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfsInitOurDomainDCs returning 0x%x\n", status);
#endif
DFSSVC_TRACE_LOW(DEFAULT, DfsInitOurDomainDCs_Exit, LOGSTATUS(status));
return( status );
}
NTSTATUS
DfsInitRemainingDomainDCs(VOID)
{
NTSTATUS status;
HANDLE dfsHandle = NULL;
IO_STATUS_BLOCK ioStatus;
ULONG cDom;
PDFS_CREATE_SPECIAL_INFO_ARG pSpcArg;
ULONG Size;
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfsInitRemainingDomainDCs()\n");
#endif
if (DfsDomainInfo.cDomains == 0) {
return STATUS_SUCCESS;
}
status = DfsOpen(&dfsHandle, NULL);
if (NT_SUCCESS(status)) {
for (cDom = 0; cDom < DfsDomainInfo.cDomains; cDom++) {
#if DBG
if (DfsSvcVerbose)
DbgPrint("Trusted domain %ws/%ws\n",
DfsDomainInfo.rgustrDomains[cDom].DnsName.Buffer,
DfsDomainInfo.rgustrDomains[cDom].FlatName.Buffer);
#endif
status = DfsCreateSpcArg(
DfsDomainInfo.rgustrDomains[cDom].FlatName.Buffer,
0,
DFS_SPECIAL_INFO_NETBIOS,
DfsDomainInfo.rgustrDomains[cDom].TrustDirection,
DfsDomainInfo.rgustrDomains[cDom].TrustType,
-1,
NULL,
&pSpcArg,
&Size);
if (status == ERROR_SUCCESS) {
status = NtFsControlFile(
dfsHandle,
NULL, // Event,
NULL, // ApcRoutine,
NULL, // ApcContext,
&ioStatus,
FSCTL_DFS_CREATE_SPECIAL_INFO,
pSpcArg,
Size,
NULL,
0);
DFSSVC_TRACE_ERROR_HIGH(status, ALL_ERROR, DfsInitRemainingDomainDCs_Error_NtFsControlFile,
LOGSTATUS(status));
free(pSpcArg);
}
status = DfsCreateSpcArg(
DfsDomainInfo.rgustrDomains[cDom].DnsName.Buffer,
0,
0,
DfsDomainInfo.rgustrDomains[cDom].TrustDirection,
DfsDomainInfo.rgustrDomains[cDom].TrustType,
-1,
NULL,
&pSpcArg,
&Size);
if (status == ERROR_SUCCESS) {
status = NtFsControlFile(
dfsHandle,
NULL, // Event,
NULL, // ApcRoutine,
NULL, // ApcContext,
&ioStatus,
FSCTL_DFS_CREATE_SPECIAL_INFO,
pSpcArg,
Size,
NULL,
0);
DFSSVC_TRACE_ERROR_HIGH(status, ALL_ERROR,
DfsInitRemainingDomainDCs_Error_NtFsControlFile2,
LOGSTATUS(status));
free(pSpcArg);
}
}
}
if (dfsHandle != NULL) {
NtClose( dfsHandle);
}
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfsInitRemainingDomainDCs returning 0x%x\n", status);
#endif
return( status );
}
NTSTATUS
_DfsGetTrustedDomainDCs(
LPWSTR LpcDomainName,
ULONG Flags)
{
NTSTATUS status;
DWORD dwErr;
HANDLE dfsHandle = NULL;
HANDLE hDs = NULL;
IO_STATUS_BLOCK ioStatus;
ULONG i, j;
PDFS_CREATE_SPECIAL_INFO_ARG pSpcArg;
ULONG NameCount = 0;
ULONG NT5Count = 0;
ULONG Size;
ULONG Timeout = 10 * 60;
ULONG TrustDirection;
ULONG TrustType;
ULONG cDom;
PDS_DOMAIN_CONTROLLER_INFO_1 pDsDomainControllerInfo1 = NULL;
PUNICODE_STRING pustrDCNames = NULL;
UNICODE_STRING ustrSiteName;
PDFS_CREATE_SITE_INFO_ARG pSiteArg;
LPWSTR Name = NULL;
WCHAR DnsDomName[MAX_PATH];
UNICODE_STRING uDomainName;
UNICODE_STRING uDomainNameDns;
UNICODE_STRING uLpcDomainName;
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfsGetTrustedDomainDCs(%ws)\n", LpcDomainName);
#endif
EnterCriticalSection(&DomListCritSection);
RtlInitUnicodeString(&uDomainName, DomainName);
RtlInitUnicodeString(&uDomainNameDns, DomainNameDns);
RtlInitUnicodeString(&uLpcDomainName, LpcDomainName);
#if DBG
if (DfsSvcVerbose)
DbgPrint("Comparing [%wZ/%wZ] to [%wZ]\n",
&uDomainName,
&uDomainNameDns,
&uLpcDomainName);
#endif
if (RtlCompareUnicodeString(&uDomainName, &uLpcDomainName, TRUE) == 0
||
RtlCompareUnicodeString(&uDomainNameDns, &uLpcDomainName, TRUE) == 0
) {
if (wcslen(DomainNameDns) <= MAX_PATH) {
wcscpy(DnsDomName, DomainNameDns);
TrustDirection = TRUST_DIRECTION_BIDIRECTIONAL;
TrustType = TRUST_TYPE_UPLEVEL;
} else {
status = ERROR_NOT_ENOUGH_MEMORY;
LeaveCriticalSection(&DomListCritSection);
goto exit_with_status;
}
} else {
for (cDom = 0; cDom < DfsDomainInfo.cDomains; cDom++) {
RtlInitUnicodeString(&uLpcDomainName, LpcDomainName);
#if DBG
if (DfsSvcVerbose)
DbgPrint("Comparing [%wZ/%wZ] to [%wZ]\n",
&DfsDomainInfo.rgustrDomains[cDom].FlatName,
&DfsDomainInfo.rgustrDomains[cDom].DnsName,
&uLpcDomainName);
#endif
if (RtlCompareUnicodeString(
&DfsDomainInfo.rgustrDomains[cDom].FlatName,
&uLpcDomainName,
TRUE) == 0
||
RtlCompareUnicodeString(
&DfsDomainInfo.rgustrDomains[cDom].DnsName,
&uLpcDomainName,
TRUE) == 0
) {
break;
}
}
if (cDom >= DfsDomainInfo.cDomains) {
status = STATUS_OBJECT_NAME_NOT_FOUND;
LeaveCriticalSection(&DomListCritSection);
goto exit_with_status;
}
if (DfsDomainInfo.rgustrDomains[cDom].DnsName.Length/sizeof(WCHAR) <= MAX_PATH) {
wcscpy(DnsDomName, DfsDomainInfo.rgustrDomains[cDom].DnsName.Buffer);
TrustDirection = DfsDomainInfo.rgustrDomains[cDom].TrustDirection;
TrustType = DfsDomainInfo.rgustrDomains[cDom].TrustType;
} else {
status = ERROR_NOT_ENOUGH_MEMORY;
LeaveCriticalSection(&DomListCritSection);
goto exit_with_status;
}
}
LeaveCriticalSection(&DomListCritSection);
status = DfsOpen(&dfsHandle, NULL);
if (NT_SUCCESS(status)) {
dwErr = DsBind(NULL, DnsDomName, &hDs);
if (dwErr == NO_ERROR) {
//
// get DC list for that domain
//
dwErr = DsGetDomainControllerInfo(
hDs,
DnsDomName,
1,
&NameCount,
&pDsDomainControllerInfo1);
#if DBG
if (DfsSvcVerbose)
DbgPrint("DsGetDomainControllerInfo(%ws) returned %d\n",
DnsDomName,
dwErr);
#endif
if (dwErr == NO_ERROR && pDsDomainControllerInfo1 != NULL) {
//
// Load Site info
//
#if DBG
if (DfsSvcVerbose)
DbgPrint("NameCount=%d\n", NameCount);
#endif
for (i = 0; i < NameCount; i++) {
Name = (Flags & DFS_SPECIAL_INFO_NETBIOS) != 0 ?
pDsDomainControllerInfo1[i].NetbiosName :
pDsDomainControllerInfo1[i].DnsHostName;
if (pDsDomainControllerInfo1[i].fDsEnabled == TRUE &&
Name != NULL &&
pDsDomainControllerInfo1[i].SiteName != NULL) {
RtlInitUnicodeString(
&ustrSiteName,
pDsDomainControllerInfo1[i].SiteName);
#if DBG
if (DfsSvcVerbose)
DbgPrint("%ws is in site %ws\n",
Name,
pDsDomainControllerInfo1[i].SiteName);
#endif
dwErr = DfsCreateSiteArg(
Name,
1,
&ustrSiteName,
&pSiteArg,
&Size);
if ( dwErr != NO_ERROR) {
status = ERROR_NOT_ENOUGH_MEMORY;
goto exit_with_status;
}
NtFsControlFile(
dfsHandle,
NULL,
NULL,
NULL,
&ioStatus,
FSCTL_DFS_CREATE_SITE_INFO,
pSiteArg,
Size,
NULL,
0);
free(pSiteArg);
}
}
//
// Convert to an array of UNICODE_STRINGS, taking only the NT5 DC's
//
for (i = NT5Count = 0; i < NameCount; i++) {
if (pDsDomainControllerInfo1[i].fDsEnabled == TRUE) {
NT5Count++;
}
}
if (NT5Count > 0) {
pustrDCNames = malloc(sizeof(UNICODE_STRING) * NT5Count);
if (pustrDCNames == NULL) {
status = ERROR_NOT_ENOUGH_MEMORY;
goto exit_with_status;
}
for (i = j = 0; i < NameCount; i++) {
Name = (Flags & DFS_SPECIAL_INFO_NETBIOS) != 0 ?
pDsDomainControllerInfo1[i].NetbiosName :
pDsDomainControllerInfo1[i].DnsHostName;
if (pDsDomainControllerInfo1[i].fDsEnabled == TRUE && Name != NULL) {
RtlInitUnicodeString(
&pustrDCNames[j],
Name);
j++;
}
}
}
#if DBG
if (DfsSvcVerbose) {
DbgPrint("DFSINIT:%ws=", LpcDomainName);
for (i = 0; i < j; i++) {
DbgPrint("%wZ ", &pustrDCNames[i]);
}
DbgPrint("\n");
DbgPrint("Our domain has %d DC's\n", j);
}
#endif
status = DfsCreateSpcArg(
LpcDomainName,
Timeout,
Flags,
TrustDirection,
TrustType,
j,
pustrDCNames,
&pSpcArg,
&Size);
if (status == ERROR_SUCCESS) {
status = NtFsControlFile(
dfsHandle,
NULL, // Event,
NULL, // ApcRoutine,
NULL, // ApcContext,
&ioStatus,
FSCTL_DFS_CREATE_SPECIAL_INFO,
pSpcArg,
Size,
NULL,
0);
free(pSpcArg);
}
if (pustrDCNames != NULL) {
free(pustrDCNames);
pustrDCNames = NULL;
}
}
} else {
status = STATUS_DS_UNAVAILABLE;
}
}
exit_with_status:
if (dfsHandle != NULL) {
NtClose( dfsHandle);
}
if (pDsDomainControllerInfo1 != NULL) {
DsFreeDomainControllerInfo(
1,
NameCount,
pDsDomainControllerInfo1);
}
if (pustrDCNames != NULL) {
free(pustrDCNames);
}
if (hDs != NULL) {
DsUnBind(&hDs);
}
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfsGetTrustedDomainDCs returning 0x%x\n", status);
#endif
return( status );
}
#define MAX_SPC_LONG_NAME_SIZE 2048
NTSTATUS
DfsGetTrustedDomainDCs(
LPWSTR LpcDomainName,
ULONG Flags)
{
LPWSTR NewDomainName = NULL;
NTSTATUS Status = STATUS_SUCCESS;
if ((LpcDomainName != NULL) &&
(*LpcDomainName != 0)) {
return _DfsGetTrustedDomainDCs(LpcDomainName, Flags);
}
NewDomainName = malloc(MAX_SPC_LONG_NAME_SIZE);
if (NewDomainName == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
while (DfsGetNextDomainName(NewDomainName, MAX_SPC_LONG_NAME_SIZE) == TRUE) {
Status = _DfsGetTrustedDomainDCs(NewDomainName, Flags);
}
free(NewDomainName);
return Status;
}
DWORD
DfsCreateSpcArg(
LPWSTR SpecialName,
ULONG Timeout,
ULONG Flags,
ULONG TrustDirection,
ULONG TrustType,
LONG NameCount,
PUNICODE_STRING pustrDCNames,
PDFS_CREATE_SPECIAL_INFO_ARG *ppSpcArg,
PULONG pSize)
{
ULONG Size;
PDFS_CREATE_SPECIAL_INFO_ARG pSpcArg;
PUNICODE_STRING ustrp;
WCHAR *wCp;
LONG i;
LONG j;
DWORD status = STATUS_SUCCESS;
UNICODE_STRING ComputerNetbiosName;
UNICODE_STRING ComputerDnsName;
ULONG ComputerNameSize;
BOOL bStatus;
WCHAR NetBIOSBuffer[MAX_COMPUTERNAME_LENGTH + 1];
RtlInitUnicodeString(&ComputerNetbiosName, NULL);
RtlInitUnicodeString(&ComputerDnsName, NULL);
ComputerNetbiosName.Buffer = NetBIOSBuffer;
ComputerNetbiosName.MaximumLength = (MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR);
ComputerNameSize = MAX_COMPUTERNAME_LENGTH + 1;
if (GetComputerNameEx(ComputerNameNetBIOS,
ComputerNetbiosName.Buffer,
&ComputerNameSize)) {
ComputerNetbiosName.Length = (USHORT)(ComputerNameSize - 1) * sizeof(WCHAR);
}
ComputerNameSize = 0;
while( TRUE ) {
bStatus = GetComputerNameEx( ComputerNameDnsFullyQualified,
ComputerDnsName.Buffer,
&ComputerNameSize );
if( bStatus == TRUE ) {
ComputerDnsName.Length = (USHORT)(ComputerNameSize - 1) * sizeof(WCHAR);
break;
}
if( GetLastError() == ERROR_MORE_DATA ) {
if( ComputerDnsName.Buffer != NULL ) {
free( ComputerDnsName.Buffer );
}
ComputerDnsName.Buffer = malloc( ComputerNameSize * sizeof(WCHAR) );
if( ComputerDnsName.Buffer == NULL ) {
ComputerDnsName.MaximumLength = 0;
break;
}
ComputerDnsName.MaximumLength = (USHORT)ComputerNameSize * sizeof(WCHAR);
} else {
break;
}
}
#if DBG
if (DfsSvcVerbose) {
DbgPrint("DfsCreateSpcArg(SpecialName=%ws,Timeout=%d,Flags=0x%x,NameCount=%d)\n",
SpecialName,
Timeout,
Flags,
NameCount);
for (i = 0; i < NameCount; i++) {
DbgPrint(" Name[%d]:%wZ\n", i, &pustrDCNames[i]);
}
}
#endif
//
// Size the buffer
//
if (NameCount > 0) {
Size = FIELD_OFFSET(DFS_CREATE_SPECIAL_INFO_ARG,Name[NameCount]) +
wcslen(SpecialName) * sizeof(WCHAR);
for (i = 0; i < NameCount; i++) {
Size += pustrDCNames[i].Length;
}
} else {
Size = sizeof(DFS_CREATE_SPECIAL_INFO_ARG) +
wcslen(SpecialName) * sizeof(WCHAR);
}
pSpcArg = malloc(Size);
if (pSpcArg != NULL) {
ZeroMemory(pSpcArg, Size);
// Marshall the info in
pSpcArg->NameCount = NameCount;
pSpcArg->Flags = Flags;
pSpcArg->TrustDirection = TrustDirection;
pSpcArg->TrustType = TrustType;
pSpcArg->Timeout = Timeout;
wCp = (WCHAR *) &pSpcArg->Name[NameCount < 0 ? 0 : NameCount];
ustrp = &pSpcArg->SpecialName;
ustrp->Buffer = wCp;
ustrp->Length = ustrp->MaximumLength = wcslen(SpecialName) * sizeof(WCHAR);
RtlCopyMemory(ustrp->Buffer, SpecialName, ustrp->Length);
wCp += ustrp->Length / sizeof(WCHAR);
for (i = 0; i < NameCount; i++) {
BOOLEAN foundDc = FALSE;
ustrp = &pSpcArg->Name[i];
ustrp->Buffer = wCp;
ustrp->Length = ustrp->MaximumLength = pustrDCNames[i].Length;
RtlCopyMemory(ustrp->Buffer, pustrDCNames[i].Buffer, ustrp->Length);
wCp += ustrp->Length / sizeof(WCHAR);
if (!foundDc) {
if ((ComputerNetbiosName.Length != 0) &&
(RtlCompareUnicodeString(&ComputerNetbiosName,
&pustrDCNames[i],
TRUE) == 0)) {
foundDc = TRUE;
}
else if ((ComputerDnsName.Length != 0) &&
(RtlCompareUnicodeString(&ComputerDnsName,
&pustrDCNames[i],
TRUE) == 0)) {
foundDc = TRUE;
}
if ((foundDc == TRUE) && (i != 0)) {
UNICODE_STRING Tmp;
Tmp = *ustrp;
*ustrp = pSpcArg->Name[0];
pSpcArg->Name[0] = Tmp;
}
}
}
POINTER_TO_OFFSET(pSpcArg->SpecialName.Buffer, pSpcArg);
for (i = 0; i < NameCount; i++) {
POINTER_TO_OFFSET(pSpcArg->Name[i].Buffer, pSpcArg);
}
*ppSpcArg = pSpcArg;
*pSize = Size;
} else {
status = ERROR_NOT_ENOUGH_MEMORY;
}
if( ComputerDnsName.Buffer != NULL ) {
free( ComputerDnsName.Buffer );
}
return status;
}
DWORD
DfsCreateSiteArg(
LPWSTR ServerName,
ULONG SiteCount,
PUNICODE_STRING pustrSiteNames,
PDFS_CREATE_SITE_INFO_ARG *ppSiteArg,
PULONG pSize)
{
ULONG i;
ULONG Size;
WCHAR *wCp;
PUNICODE_STRING ustrp;
PDFS_CREATE_SITE_INFO_ARG pSiteArg;
DWORD status = STATUS_SUCCESS;
DFSSVC_TRACE_NORM(DEFAULT, DfsCreateSiteArg_Entry,
LOGWSTR_CHK(ServerName)
LOGULONG(SiteCount)
LOGUSTR(*pustrSiteNames));
// Size the buffer
Size = FIELD_OFFSET(DFS_CREATE_SITE_INFO_ARG,SiteName[SiteCount]) +
wcslen(ServerName) * sizeof(WCHAR);
for (i = 0; i < SiteCount; i++)
Size += pustrSiteNames[i].Length;
pSiteArg = malloc(Size);
if (pSiteArg != NULL) {
// Marshall the info in
pSiteArg->SiteCount = SiteCount;
wCp = (WCHAR *) &pSiteArg->SiteName[SiteCount];
ustrp = &pSiteArg->ServerName;
ustrp->Buffer = wCp;
ustrp->Length = ustrp->MaximumLength = wcslen(ServerName) * sizeof(WCHAR);
RtlCopyMemory(ustrp->Buffer,ServerName,ustrp->Length);
wCp += ustrp->Length / sizeof(WCHAR);
for (i = 0; i < SiteCount; i++) {
ustrp = &pSiteArg->SiteName[i];
ustrp->Buffer = wCp;
ustrp->Length = ustrp->MaximumLength = pustrSiteNames[i].Length;
RtlCopyMemory(ustrp->Buffer,pustrSiteNames[i].Buffer,ustrp->Length);
wCp += ustrp->Length / sizeof(WCHAR);
}
POINTER_TO_OFFSET(pSiteArg->ServerName.Buffer, pSiteArg);
for (i = 0; i < SiteCount; i++) {
POINTER_TO_OFFSET(pSiteArg->SiteName[i].Buffer, pSiteArg);
}
*ppSiteArg = pSiteArg;
*pSize = Size;
} else {
status = ERROR_NOT_ENOUGH_MEMORY;
}
DFSSVC_TRACE_NORM(DEFAULT, DfsCreateSiteArg_Exit,
LOGSTATUS(status)
LOGWSTR_CHK(ServerName)
LOGULONG(SiteCount)
LOGUSTR(*pustrSiteNames));
return status;
}
NTSTATUS
DfsDomainReferral(
LPWSTR wszDomain,
LPWSTR wszShare)
{
NTSTATUS Status;
DWORD dwErr;
LPWSTR *List = NULL;
PUNICODE_STRING pustr;
HANDLE dfsHandle;
IO_STATUS_BLOCK ioStatus;
ULONG Count;
ULONG Size;
PDFS_CREATE_SPECIAL_INFO_ARG pSpcArg;
ULONG i;
DFSSVC_TRACE_HIGH(DEFAULT,DfsDomainReferral_Entry,
LOGWSTR_CHK(wszDomain)
LOGWSTR_CHK(wszShare));
#if DBG
if (DfsSvcVerbose) {
DbgPrint("DfsDomainReferral()\n", 0);
DbgPrint("\twszDomain:%ws\n", wszDomain);
DbgPrint("\twszShare:%ws\n", wszShare);
}
#endif
dwErr = DfsGetFtServersFromDs(pLdap, wszDomain, wszShare, &List);
if (dwErr != NO_ERROR || List == NULL) {
Status = STATUS_OBJECT_NAME_NOT_FOUND;
} else {
for (Count = 0; List[Count]; Count++)
/* NOTHING */;
pustr = malloc(sizeof(UNICODE_STRING) * Count);
if (pustr != NULL) {
for (i = 0; i < Count; i++) {
RtlInitUnicodeString(&pustr[i], List[i]);
if (pustr[i].Buffer[0] == L'\\') {
pustr[i].Buffer++;
pustr[i].Length -= sizeof(WCHAR);
pustr[i].MaximumLength -= sizeof(WCHAR);
}
}
Status = DfsCreateSpcArg(
wszShare,
60 * 15, // 15 min
DFS_SPECIAL_INFO_PRIMARY,
0,
0,
Count,
pustr,
&pSpcArg,
&Size);
if (Status == ERROR_SUCCESS) {
Status = DfsOpen(&dfsHandle, NULL);
if (NT_SUCCESS(Status)) {
NtFsControlFile(
dfsHandle,
NULL, // Event,
NULL, // ApcRoutine,
NULL, // ApcContext,
&ioStatus,
FSCTL_DFS_CREATE_FTDFS_INFO,
pSpcArg,
Size,
NULL,
0);
NtClose( dfsHandle);
}
//
// Rummage through the DS, loading the site info for the
// machines we found.
//
if (NT_SUCCESS(Status)) {
DfsLoadSiteTableFromDs(
pLdap,
wszShare,
Count,
pustr);
}
free(pSpcArg);
}
free(pustr);
}
NetApiBufferFree(List);
}
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfsDomainReferral exit 0x%x\n", Status);
#endif
return Status;
}
BOOLEAN
DfsGetNextDomainName(
LPWSTR DomName,
ULONG Size)
{
HANDLE dfsHandle;
IO_STATUS_BLOCK ioStatus;
NTSTATUS Status;
Status = DfsOpen(&dfsHandle, NULL);
if (NT_SUCCESS(Status)) {
Status = NtFsControlFile(
dfsHandle,
NULL, // Event,
NULL, // ApcRoutine,
NULL, // ApcContext,
&ioStatus,
FSCTL_DFS_GET_NEXT_LONG_DOMAIN_NAME,
NULL,
0,
DomName,
Size);
NtClose( dfsHandle);
}
return (Status == STATUS_SUCCESS) ? TRUE : FALSE;
}