windows-nt/Source/XPSP1/NT/base/fs/dfs/dfsm/server/setup.cxx
2020-09-26 16:20:57 +08:00

2440 lines
63 KiB
C++

//+-------------------------------------------------------------------------
//
// File: setup.cxx
//
// Contents: This module contains the functions which remote setup
//
// History: 11-Feb-1998 JHarper Created
//
//--------------------------------------------------------------------------
//#include <ntos.h>
//#include <ntrtl.h>
//#include <nturtl.h>
//#include <dfsfsctl.h>
//#include <windows.h>
#include "headers.hxx"
#pragma hdrstop
extern "C" {
#include <srvfsctl.h>
#include <winldap.h>
#include <dsgetdc.h>
#include "dfsmsrv.h"
}
#include "registry.hxx"
#include "setup.hxx"
#include "dfsmwml.h"
#include <winioctl.h>
//
// Until we get the schema right in the DS, we have to set our own SD on
// certain objects
//
#include <aclapi.h>
#include <permit.h>
DECLARE_DEBUG(Setup)
DECLARE_INFOLEVEL(Setup)
#if DBG == 1
#define dprintf(x) SetupInlineDebugOut x
# else
#define dprintf(x)
#endif
DWORD
InitStdVolumeObjectStorage(VOID);
DWORD
GetShareAndPath(
IN LPWSTR wszShare,
OUT LPWSTR wszPath);
DWORD
CreateFtRootVolRegInfo(
LPWSTR wszObjectName,
LPWSTR wszFTDfsConfigDN,
LPWSTR wszDomainName,
LPWSTR wszDfsName,
LPWSTR wszServerName,
LPWSTR wszShareName,
LPWSTR wszSharePath,
BOOLEAN fNewFTDfs);
DWORD
CreateStdVolumeObject(
LPWSTR wszObjectName,
LPWSTR pwszEntryPath,
LPWSTR pwszServer,
LPWSTR pwszShare,
LPWSTR pwszComment,
GUID *guidVolume);
DWORD
CreateFtVolumeObject(
LPWSTR wszObjectName,
LPWSTR wszFTDfsConfigDN,
LPWSTR wszDomainName,
LPWSTR wszDfsName,
LPWSTR wszServerName,
LPWSTR wszShareName,
LPWSTR wszSharePath,
LPWSTR wszComment,
BOOLEAN fNewFTDfs);
DWORD
StoreLocalVolInfo(
IN GUID *pVolumeID,
IN PWSTR pwszStorageID,
IN PWSTR pwszShareName,
IN PWSTR pwszEntryPath,
IN ULONG ulVolumeType);
DWORD
LdapFlushTable(
void);
DWORD
DfspCreateRootServerList(
IN LDAP *pldap,
IN LPWSTR wszServerShare,
IN LPWSTR wszDfsConfigDN,
IN PDFSM_ROOT_LIST *ppRootList);
VOID GuidToString(
IN GUID *pGuid,
OUT PWSTR pwszGuid);
extern PLDAP pLdapConnection;
//+-------------------------------------------------------------------------
//
// Function: DfsmInitLocalPartitions
//
// Synopsis: Tell dfs.sys to read the local volume part of the registry
// Sends FSCTL_DFS_INIT_LOCAL_PARTITIONS to dfs.sys
//
//--------------------------------------------------------------------------
NTSTATUS
DfsmInitLocalPartitions(
VOID)
{
NTSTATUS NtStatus;
HANDLE DriverHandle = NULL;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING DfsServerName;
RtlInitUnicodeString(&DfsServerName, DFS_SERVER_NAME);
InitializeObjectAttributes(
&objectAttributes,
&DfsServerName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
NtStatus = NtCreateFile(
&DriverHandle,
SYNCHRONIZE | FILE_WRITE_DATA,
&objectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmInitLocalPartitions_Error_NtCreateFile,
LOGSTATUS(NtStatus));
if (NT_SUCCESS(NtStatus)) {
NtStatus = NtFsControlFile(
DriverHandle,
NULL, // Event,
NULL, // ApcRoutine,
NULL, // ApcContext,
&IoStatusBlock,
FSCTL_DFS_INIT_LOCAL_PARTITIONS,
NULL,
0,
NULL,
0);
DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmInitLocalPartitions_Error_NtFsCOntrolFile,
LOGSTATUS(NtStatus));
NtClose(DriverHandle);
}
return NtStatus;
}
//+-------------------------------------------------------------------------
//
// Function: DfsmStartDfs
//
// Synopsis: Tell dfs.sys to turn itself on
// Sends FSCTL_DFS_START_DFS to dfs.sys
//
//--------------------------------------------------------------------------
NTSTATUS
DfsmStartDfs(
VOID)
{
NTSTATUS NtStatus;
HANDLE DriverHandle = NULL;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING DfsServerName;
RtlInitUnicodeString(&DfsServerName, DFS_SERVER_NAME);
InitializeObjectAttributes(
&objectAttributes,
&DfsServerName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
NtStatus = NtCreateFile(
&DriverHandle,
SYNCHRONIZE | FILE_WRITE_DATA,
&objectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmStartDfs_Error_NtCreateFile,
LOGSTATUS(NtStatus));
if (NT_SUCCESS(NtStatus)) {
NtStatus = NtFsControlFile(
DriverHandle,
NULL, // Event,
NULL, // ApcRoutine,
NULL, // ApcContext,
&IoStatusBlock,
FSCTL_DFS_START_DFS,
NULL,
0,
NULL,
0);
DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmStartDfs_Error_NtFsControlFile,
LOGSTATUS(NtStatus));
NtClose(DriverHandle);
}
return NtStatus;
}
//+-------------------------------------------------------------------------
//
// Function: DfsmStopDfs
//
// Synopsis: Tell dfs.sys to turn itself off
// Sends FSCTL_DFS_STOP_DFS to dfs.sys
//
//--------------------------------------------------------------------------
NTSTATUS
DfsmStopDfs(
VOID)
{
NTSTATUS NtStatus;
HANDLE DriverHandle = NULL;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING DfsServerName;
RtlInitUnicodeString(&DfsServerName, DFS_SERVER_NAME);
InitializeObjectAttributes(
&objectAttributes,
&DfsServerName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
NtStatus = NtCreateFile(
&DriverHandle,
SYNCHRONIZE | FILE_WRITE_DATA,
&objectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmStopDfs_Error_NtCreateFile,
LOGSTATUS(NtStatus));
if (NT_SUCCESS(NtStatus)) {
NtStatus = NtFsControlFile(
DriverHandle,
NULL, // Event,
NULL, // ApcRoutine,
NULL, // ApcContext,
&IoStatusBlock,
FSCTL_DFS_STOP_DFS,
NULL,
0,
NULL,
0);
DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmStopDfs_Error_NtFsControlFile,
LOGSTATUS(NtStatus));
NtClose(DriverHandle);
}
return NtStatus;
}
//+-------------------------------------------------------------------------
//
// Function: DfsmResetPkt
//
// Synopsis: Tell dfs.sys to throw away all state and turn off
// Sends FSCTL_DFS_RESET_PKT to dfs.sys
//
//--------------------------------------------------------------------------
NTSTATUS
DfsmResetPkt(
VOID)
{
NTSTATUS NtStatus;
HANDLE DriverHandle = NULL;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING DfsServerName;
RtlInitUnicodeString(&DfsServerName, DFS_SERVER_NAME);
InitializeObjectAttributes(
&objectAttributes,
&DfsServerName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
NtStatus = NtCreateFile(
&DriverHandle,
SYNCHRONIZE | FILE_WRITE_DATA,
&objectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmResetPkt_Error_NtCreateFile,
LOGSTATUS(NtStatus));
//
// Toss the Pkt
//
if (NT_SUCCESS(NtStatus)) {
NtStatus = NtFsControlFile(
DriverHandle,
NULL, // Event,
NULL, // ApcRoutine,
NULL, // ApcContext,
&IoStatusBlock,
FSCTL_DFS_RESET_PKT,
NULL,
0,
NULL,
0);
DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmResetPkt_Error_NtFsControlFile,
LOGSTATUS(NtStatus));
NtClose(DriverHandle);
}
return NtStatus;
}
//+-------------------------------------------------------------------------
//
// Function: DfsmPktFlushCache
//
// Synopsis: Tell dfs.sys to turn itself off
// Sends FSCTL_DFS_PKT_FLUSH_CACHE to mup.sys
//
//--------------------------------------------------------------------------
NTSTATUS
DfsmPktFlushCache(
VOID)
{
NTSTATUS NtStatus;
HANDLE DriverHandle = NULL;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING DfsDriverName;
WCHAR EntryPath[5];
//
// Flush the local/client side pkt, too
//
RtlInitUnicodeString(&DfsDriverName, DFS_DRIVER_NAME);
InitializeObjectAttributes(
&objectAttributes,
&DfsDriverName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
NtStatus = NtCreateFile(
&DriverHandle,
SYNCHRONIZE | FILE_WRITE_DATA,
&objectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmPktFlushCache_Error_NtCreateFile,
LOGSTATUS(NtStatus));
if (NT_SUCCESS(NtStatus)) {
wcscpy(EntryPath, L"*");
NtStatus = NtFsControlFile(
DriverHandle,
NULL, // Event,
NULL, // ApcRoutine,
NULL, // ApcContext,
&IoStatusBlock,
FSCTL_DFS_PKT_FLUSH_CACHE,
EntryPath,
wcslen(EntryPath) * sizeof(WCHAR),
NULL,
0);
DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmPktFlushCache_Error_NtFsControlFile,
LOGSTATUS(NtStatus));
NtClose(DriverHandle);
}
return NtStatus;
}
//+-------------------------------------------------------------------------
//
// Function: DfsmMarkStalePktEntries
//
// Synopsis: Tell dfs.sys to throw away all state and turn off
// Sends FSCTL_DFS_MARK_STALE_PKT_ENTRIES to dfs.sys
//
//--------------------------------------------------------------------------
NTSTATUS
DfsmMarkStalePktEntries(
VOID)
{
NTSTATUS NtStatus;
HANDLE DriverHandle = NULL;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING DfsServerName;
RtlInitUnicodeString(&DfsServerName, DFS_SERVER_NAME);
InitializeObjectAttributes(
&objectAttributes,
&DfsServerName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
NtStatus = NtCreateFile(
&DriverHandle,
SYNCHRONIZE | FILE_WRITE_DATA,
&objectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmMarkStalePktEntries_Error_NtCreateFile,
LOGSTATUS(NtStatus));
//
// Toss the Pkt
//
if (NT_SUCCESS(NtStatus)) {
NtStatus = NtFsControlFile(
DriverHandle,
NULL, // Event,
NULL, // ApcRoutine,
NULL, // ApcContext,
&IoStatusBlock,
FSCTL_DFS_MARK_STALE_PKT_ENTRIES,
NULL,
0,
NULL,
0);
DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmMarkStalePktEntries_Error_NtFsControlFile,
LOGSTATUS(NtStatus));
NtClose(DriverHandle);
}
return NtStatus;
}
//+-------------------------------------------------------------------------
//
// Function: DfsmFlushStalePktEntries
//
// Synopsis: Tell dfs.sys to throw away all state and turn off
// Sends FSCTL_DFS_FLUSH_STALE_PKT_ENTRIES to dfs.sys
//
//--------------------------------------------------------------------------
NTSTATUS
DfsmFlushStalePktEntries(
VOID)
{
NTSTATUS NtStatus;
HANDLE DriverHandle = NULL;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING DfsServerName;
RtlInitUnicodeString(&DfsServerName, DFS_SERVER_NAME);
InitializeObjectAttributes(
&objectAttributes,
&DfsServerName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
NtStatus = NtCreateFile(
&DriverHandle,
SYNCHRONIZE | FILE_WRITE_DATA,
&objectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmFlushStalePktEntries_Error_NtCreateFile,
LOGSTATUS(NtStatus));
//
// Toss the Pkt
//
if (NT_SUCCESS(NtStatus)) {
NtStatus = NtFsControlFile(
DriverHandle,
NULL, // Event,
NULL, // ApcRoutine,
NULL, // ApcContext,
&IoStatusBlock,
FSCTL_DFS_FLUSH_STALE_PKT_ENTRIES,
NULL,
0,
NULL,
0);
DFSM_TRACE_ERROR_HIGH(NtStatus, ALL_ERROR, DfsmFlushStalePktEntries_Error_NtFsControl,
LOGSTATUS(NtStatus));
NtClose(DriverHandle);
}
return NtStatus;
}
//+----------------------------------------------------------------------------
//
// Function: SetupStdDfs
//
// Synopsis: Does necessary setup to make this Dfs a root of the Dfs.
//
// Arguments: [wszComputerName] -- The name of the computer
// [wszDfsRootShare] -- The share to use as the Dfs root.
// [wszComment] -- Comment for root share
// [dwFlags] -- Flags for operation
//
// Returns: Win32 error from configuring the root storages etc.
//
//-----------------------------------------------------------------------------
DWORD
SetupStdDfs(
LPWSTR wszComputerName,
LPWSTR wszDfsRootShare,
LPWSTR wszComment,
DWORD dwFlags,
LPWSTR wszDfsRoot)
{
DWORD dwErr = ERROR_SUCCESS;
GUID guid;
WCHAR wszDfsRootPath[MAX_PATH+1];
PWCHAR wszDfsRootPrefix = NULL;
TCHAR szPath[] = TEXT("A:\\");
//
// Figure out the share path for the Root Dfs share
//
if (dwErr == ERROR_SUCCESS) {
if (wszDfsRoot == NULL) {
dwErr = GetShareAndPath( wszDfsRootShare, wszDfsRootPath );
} else {
wcscpy(wszDfsRootPath, wszDfsRoot);
}
}
// Check if we are trying to create a root on removable media.
// Return an error if we are.
// We can't allow this because, for example, if the root is a floppy
// that is not present at boot time, the system hangs and doesn't
// even boot up. It isn't possible to detect this at boot time and ignore
// the drive, so we must prevent such roots from existing at all.
if(dwErr == ERROR_SUCCESS) {
szPath[0] = (TCHAR)wszDfsRootPath[0];
if (GetDriveType(szPath) != DRIVE_FIXED) {
dwErr = ERROR_INVALID_MEDIA;
}
}
//
// We have all the info we need now. Lets get to work....
//
// 1. Initialize the volume object section in the registry.
//
// 2. Initialize (ie, create if necessary) the storage used for the
// Dfs root.
//
// 3. Create the root volume object.
//
// 4. Configure the root volume as a local volume by updating the
// LocalVolumes section in the registry.
//
//
// Initialize the Dfs Manager Volume Object Store
//
if (dwErr == ERROR_SUCCESS) {
dwErr = InitStdVolumeObjectStorage();
}
if (dwErr == ERROR_SUCCESS) {
dprintf((DEB_TRACE,
"Setting [%ws] as Dfs storage root...\n", wszDfsRootPath));
dwErr = DfsReInitGlobals(wszComputerName, DFS_MANAGER_SERVER );
if (pwszDfsRootName != NULL)
wcscpy(wszComputerName, pwszDfsRootName);
if (dwErr == ERROR_SUCCESS) {
wszDfsRootPrefix = new WCHAR[1 +
wcslen(wszComputerName) +
1 +
wcslen(wszDfsRootShare) +
1];
if (wszDfsRootPrefix == NULL) {
dwErr = ERROR_OUTOFMEMORY;
}
}
if (dwErr == ERROR_SUCCESS) {
wszDfsRootPrefix[0] = UNICODE_PATH_SEP;
wcscpy( &wszDfsRootPrefix[1], wszComputerName );
wcscat( wszDfsRootPrefix, UNICODE_PATH_SEP_STR );
wcscat( wszDfsRootPrefix, wszDfsRootShare );
dwErr = CreateStdVolumeObject(
DOMAIN_ROOT_VOL, // Name of volume object
wszDfsRootPrefix, // EntryPath of volume
wszComputerName, // Server name
wszDfsRootShare, // Share name
wszComment, // Comment
&guid); // Id of created volume
}
if (dwErr == ERROR_SUCCESS) {
dwErr = StoreLocalVolInfo(
&guid,
wszDfsRootPath,
wszDfsRootShare,
wszDfsRootPrefix,
DFS_VOL_TYPE_DFS | DFS_VOL_TYPE_REFERRAL_SVC);
}
if (wszDfsRootPrefix != NULL)
delete [] wszDfsRootPrefix;
if (dwErr != ERROR_SUCCESS)
dwErr = ERROR_INVALID_FUNCTION;
if (dwErr == ERROR_SUCCESS) {
DWORD dwErr;
CRegKey cregVolumesDir( HKEY_LOCAL_MACHINE, &dwErr, VOLUMES_DIR );
if (dwErr == ERROR_SUCCESS) {
CRegSZ cregRootShare(
cregVolumesDir,
ROOT_SHARE_VALUE_NAME,
wszDfsRootShare );
dwErr = cregRootShare.QueryErrorStatus();
}
}
}
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: SetupFtDfs
//
// Synopsis: Completes necessary setup to make this Dfs an FtDfs root
//
// Arguments: [wszServerName] -- The name of the machine
// [wszDomainName] -- Domain the machine is in
// [wszDfsRootShare] -- The share to use as the FtDfs root.
// [wszFtDfsName] -- The name for the FtDfs
// [wszComment] -- Comment for root share
// [wszConfigDN] -- The obj name to create
// [NewFtDfs] -- TRUE to create new, FALSE to join existing
// [dwFlags] -- Flags
//
// Returns: Win32 error from configuring the root storages etc.
//
//-----------------------------------------------------------------------------
DWORD
SetupFtDfs(
LPWSTR wszServerName,
LPWSTR wszDomainName,
LPWSTR wszRootShare,
LPWSTR wszFtDfsName,
LPWSTR wszComment,
LPWSTR wszConfigDN,
BOOLEAN NewFtDfs,
DWORD dwFlags)
{
DWORD dwErr = ERROR_SUCCESS;
WCHAR wszRootSharePath[MAX_PATH+1];
WCHAR wszServerShare[MAX_PATH+1];
TCHAR szPath[] = TEXT("A:\\");
dwErr = GetShareAndPath( wszRootShare, wszRootSharePath );
if (dwErr != ERROR_SUCCESS) {
dprintf((
DEB_ERROR,
"Win32 Error %d getting share path for %ws\n",
dwErr, wszRootShare));
goto Cleanup;
}
// Check if we are trying to create a root on removable media.
// Return an error if we are.
// We can't allow this because, for example, if the root is a floppy
// that is not present at boot time, the system hangs and doesn't
// even boot up. It isn't possible to detect this at boot time and ignore
// the drive, so we must prevent such roots from existing at all.
if(dwErr == ERROR_SUCCESS) {
szPath[0] = (TCHAR)wszRootSharePath[0];
if (GetDriveType(szPath) != DRIVE_FIXED) {
dwErr = ERROR_INVALID_MEDIA;
goto Cleanup;
}
}
wsprintf(
wszServerShare,
L"\\\\%ws\\%ws",
wszServerName,
wszRootShare);
//
// Create the DfsHost root entry in the registry
//
dwErr = CreateFtRootVolRegInfo(
DOMAIN_ROOT_VOL,
wszConfigDN,
wszDomainName,
wszFtDfsName,
wszServerName,
wszRootShare,
wszRootSharePath,
NewFtDfs);
//
// Reinitialize global stuff
//
if (dwErr == ERROR_SUCCESS) {
dwErr = DfsReInitGlobals(
wszFtDfsName,
DFS_MANAGER_FTDFS);
}
//
// Finally, create the root volume object
//
if (dwErr == ERROR_SUCCESS) {
dwErr = CreateFtVolumeObject(
DOMAIN_ROOT_VOL,
wszConfigDN,
wszDomainName,
wszFtDfsName,
wszServerName,
wszRootShare,
wszRootSharePath,
wszComment,
NewFtDfs);
}
if (dwErr == ERROR_SUCCESS) {
dprintf((
DEB_TRACE, "Successfully created FT-Dfs Configuration!\n"));
goto Cleanup;
}
dprintf((
DEB_ERROR, "CreateFtVolumeObject failed with error %d\n", dwErr));
Cleanup:
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: GetShareAndPath
//
// Synopsis: Returns the share path for a share on the local machine
//
// Arguments: [wszShare] -- Name of share
//
// [wszPath] -- On return, share path of wszShare
//
// Returns: [ERROR_SUCCESS] -- Successfully returning share path
//
// Win32 error from NetShareGetInfo
//
//-----------------------------------------------------------------------------
DWORD
GetShareAndPath(
IN LPWSTR wszShare,
OUT LPWSTR wszPath)
{
DWORD dwErr;
PSHARE_INFO_2 pshi2;
dwErr = NetShareGetInfo(
NULL, // Server (local machine)
wszShare, // Share Name
2, // Level,
(LPBYTE *) &pshi2); // Buffer
if (dwErr == ERROR_SUCCESS) {
wcscpy( wszPath, pshi2->shi2_path );
NetApiBufferFree( pshi2 );
}
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: CreateFtRootVolRegInfo
//
// Synopsis: Creates root vol info in the registry
//
// Arguments: [wszObjectName] -- Name of volume object
// [wszFTDfsConfigDN] -- The DN of the FTDfs config object in DS
// [wszDomainName] -- Name of FTDfs domain
// [wszDfsName] -- Name of Dfs
// [wszServerName] -- Name of root server
// [wszShareName] -- Name of root share
// [fNewFTDfs] -- If true, this is a new FTDfs
//
// Returns:
//
//-----------------------------------------------------------------------------
DWORD
CreateFtRootVolRegInfo(
LPWSTR wszObjectName,
LPWSTR wszFTDfsConfigDN,
LPWSTR wszDomainName,
LPWSTR wszDfsName,
LPWSTR wszServerName,
LPWSTR wszShareName,
LPWSTR wszSharePath,
BOOLEAN fNewFTDfs)
{
DWORD dwErr;
WCHAR wszFullObjectName[ MAX_PATH ];
WCHAR wszDfsPrefix[ MAX_PATH ];
GUID idVolume;
wcscpy( wszDfsPrefix, UNICODE_PATH_SEP_STR );
wcscat( wszDfsPrefix, wszDomainName );
wcscat( wszDfsPrefix, UNICODE_PATH_SEP_STR );
wcscat( wszDfsPrefix, wszDfsName );
wcscpy( wszFullObjectName, LDAP_VOLUMES_DIR );
wcscat( wszFullObjectName, wszObjectName );
//
// Create the volumes dir key that indicates that this machine is to
// be a root of an FTDfs
//
CRegKey cregVolumesDir( HKEY_LOCAL_MACHINE, VOLUMES_DIR );
dwErr = cregVolumesDir.QueryErrorStatus();
if (dwErr == ERROR_SUCCESS) {
CRegSZ cregRootShare(
cregVolumesDir,
ROOT_SHARE_VALUE_NAME,
wszShareName );
dwErr = cregRootShare.QueryErrorStatus();
if (dwErr == ERROR_SUCCESS) {
CRegSZ cregFTDfs(
cregVolumesDir,
FTDFS_VALUE_NAME,
wszDfsName);
CRegSZ cregFTDfsConfigDN(
cregVolumesDir,
FTDFS_DN_VALUE_NAME,
wszFTDfsConfigDN);
dwErr = cregFTDfs.QueryErrorStatus();
if (dwErr == ERROR_SUCCESS) {
dwErr = cregFTDfsConfigDN.QueryErrorStatus();
if (dwErr != ERROR_SUCCESS)
cregFTDfs.Delete();
}
}
}
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: CreateFtVolumeObject
//
// Synopsis: Creates root vol object
//
// Arguments: [wszObjectName] -- Name of volume object
// [wszFTDfsConfigDN] -- The DN of the FTDfs config object in DS
// [wszDomainName] -- Name of FTDfs domain
// [wszDfsName] -- Name of Dfs
// [wszServerName] -- Name of root server
// [wszShareName] -- Name of root share
// [wszComment] -- Comment for root
// [fNewFTDfs] -- If true, this is a new FTDfs
//
// Returns:
//
//-----------------------------------------------------------------------------
DWORD
CreateFtVolumeObject(
LPWSTR wszObjectName,
LPWSTR wszFTDfsConfigDN,
LPWSTR wszDomainName,
LPWSTR wszDfsName,
LPWSTR wszServerName,
LPWSTR wszShareName,
LPWSTR wszSharePath,
LPWSTR wszComment,
BOOLEAN fNewFTDfs)
{
DWORD dwErr = ERROR_SUCCESS;
WCHAR wszFullObjectName[ MAX_PATH ];
WCHAR wszDfsPrefix[ MAX_PATH ];
GUID idVolume;
wcscpy( wszDfsPrefix, UNICODE_PATH_SEP_STR );
wcscat( wszDfsPrefix, wszDomainName );
wcscat( wszDfsPrefix, UNICODE_PATH_SEP_STR );
wcscat( wszDfsPrefix, wszDfsName );
wcscpy( wszFullObjectName, LDAP_VOLUMES_DIR );
wcscat( wszFullObjectName, wszObjectName );
if (fNewFTDfs) {
//
// Generate a Guid for the new Volume
//
UuidCreate( &idVolume );
dwErr = DfsManagerCreateVolumeObject(
wszFullObjectName,
wszDfsPrefix,
wszServerName,
wszShareName,
wszComment,
&idVolume);
} else {
dwErr = DfsManagerAddService(
wszFullObjectName,
wszServerName,
wszShareName,
&idVolume);
}
//
// Write the root local vol info into the registry
//
if (dwErr == ERROR_SUCCESS) {
dwErr = StoreLocalVolInfo(
&idVolume,
wszSharePath,
wszShareName,
wszDfsPrefix,
DFS_VOL_TYPE_DFS | DFS_VOL_TYPE_REFERRAL_SVC);
if (dwErr == ERROR_SUCCESS) {
dwErr = LdapFlushTable();
}
}
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: CreateStdVolumeObject
//
// Synopsis: Creates a volume object to bootstrap the Dfs namespace.
//
// Arguments: [pwszObjectName] -- The name of the volume object, relative
// to VOLUMES_DIR
// [pwszEntryPath] -- EntryPath of the volume.
// [pwszServer] -- Name of server used to access this Dfs volume
// [pwszShare] -- Name of share used to access this Dfs volume
// [pwszComment] -- Comment to stamp on the volume object.
// [guidVolume] -- ID of newly create dfs volume
//
// Returns:
//
//-----------------------------------------------------------------------------
DWORD
CreateStdVolumeObject(
LPWSTR wszObjectName,
LPWSTR pwszEntryPath,
LPWSTR pwszServer,
LPWSTR pwszShare,
LPWSTR pwszComment,
GUID *guidVolume)
{
DWORD dwErr;
WCHAR wszFullObject[ MAX_PATH ];
//
// First, compute the full object name, storage ids, and machine name.
//
wcscpy( wszFullObject, VOLUMES_DIR );
wcscat( wszFullObject, wszObjectName );
//
// Next, get a guid for this volume
//
UuidCreate( guidVolume );
//
// Lastly, create this volume object
//
dwErr = DfsManagerCreateVolumeObject(
wszFullObject,
pwszEntryPath,
pwszServer,
pwszShare,
pwszComment,
guidVolume);
if (dwErr == ERROR_SUCCESS) {
dprintf((DEB_TRACE,"Successfully inited Dfs Manager Volume [%ws]...\n", pwszEntryPath));
}
return(dwErr);
}
//+----------------------------------------------------------------------------
//
// Function: InitStdVolumeObjectStorage
//
// Synopsis: Initializes the Dfs Manager Volume Object store.
//
// Arguments: None
//
// Returns: DWORD from registry operations.
//
//-----------------------------------------------------------------------------
DWORD
InitStdVolumeObjectStorage()
{
DWORD dwErr;
CRegKey *pcregVolumeObjectStore;
pcregVolumeObjectStore = new CRegKey(HKEY_LOCAL_MACHINE, VOLUMES_DIR );
if (pcregVolumeObjectStore != NULL) {
dwErr = pcregVolumeObjectStore->QueryErrorStatus();
delete pcregVolumeObjectStore;
} else {
dwErr = ERROR_OUTOFMEMORY;
}
if (dwErr == ERROR_SUCCESS) {
dprintf((DEB_TRACE,"Successfully inited Dfs Manager Volume Storage...\n"));
}
return(dwErr);
}
//+----------------------------------------------------------------------------
//
// Function: StoreLocalVolInfo
//
// Synopsis: Stores information about a local volume in the registry.
//
// Arguments: [pVolumeID] -- Id of dfs volume
// [pwszStorageId] -- Storage used by dfs volume
// [pwszShareName] -- LM Share used to access dfs volume
// [pwszEntryPath] -- EntryPath of dfs volume
// [ulVolumeType] -- Type of dfs volume. See DFS_VOL_TYPE_xxx
//
// Returns: DWORD from registry operations.
//
//-----------------------------------------------------------------------------
extern VOID
GuidToString(
IN GUID *pID,
OUT PWSTR pwszID);
DWORD
StoreLocalVolInfo(
IN GUID *pVolumeID,
IN PWSTR pwszStorageID,
IN PWSTR pwszShareName,
IN PWSTR pwszEntryPath,
IN ULONG ulVolumeType)
{
DWORD dwErr;
WCHAR wszLvolKey[_MAX_PATH];
UNICODE_STRING ustrNtStorageId;
PWCHAR pwcGuid;
wcscpy(wszLvolKey, REG_KEY_LOCAL_VOLUMES);
wcscat(wszLvolKey, UNICODE_PATH_SEP_STR);
pwcGuid = wszLvolKey + wcslen(wszLvolKey);
ASSERT( *pwcGuid == UNICODE_NULL );
GuidToString( pVolumeID, pwcGuid );
if (!RtlDosPathNameToNtPathName_U(
pwszStorageID,
&ustrNtStorageId,
NULL,
NULL)) {
return(ERROR_OUTOFMEMORY);
} else {
ustrNtStorageId.Buffer[ustrNtStorageId.Length/sizeof(WCHAR)] = UNICODE_NULL;
}
CRegKey rkeyLvol(HKEY_LOCAL_MACHINE, wszLvolKey, KEY_WRITE, NULL, REG_OPTION_NON_VOLATILE);
dwErr = rkeyLvol.QueryErrorStatus();
if (dwErr != ERROR_SUCCESS) {
RtlFreeUnicodeString(&ustrNtStorageId);
return(dwErr);
}
CRegSZ rvEntryPath((const CRegKey &) rkeyLvol, REG_VALUE_ENTRY_PATH, pwszEntryPath);
CRegSZ rvShortEntryPath((const CRegKey &) rkeyLvol, REG_VALUE_SHORT_PATH, pwszEntryPath);
CRegDWORD rvEntryType((const CRegKey &) rkeyLvol, REG_VALUE_ENTRY_TYPE, ulVolumeType);
CRegSZ rvStorageId((const CRegKey &) rkeyLvol, REG_VALUE_STORAGE_ID, ustrNtStorageId.Buffer);
CRegSZ rvShareName((const CRegKey &) rkeyLvol, REG_VALUE_SHARE_NAME, pwszShareName);
RtlFreeUnicodeString(&ustrNtStorageId);
if (ERROR_SUCCESS != (dwErr = rvEntryPath.QueryErrorStatus()) ||
ERROR_SUCCESS != (dwErr = rvShortEntryPath.QueryErrorStatus()) ||
ERROR_SUCCESS != (dwErr = rvEntryType.QueryErrorStatus()) ||
ERROR_SUCCESS != (dwErr = rvStorageId.QueryErrorStatus()) ||
ERROR_SUCCESS != (dwErr = rvShareName.QueryErrorStatus())) {
rkeyLvol.Delete();
} else {
dprintf((DEB_TRACE,"Successfully stored local volume info for [%ws]\n", pwszEntryPath));
}
return(dwErr);
}
//+----------------------------------------------------------------------------
//
// Function: DfsRemoveRoot
//
// Synopsis: Removes the registry info that makes a machine a root
//
// Arguments: None
//
// Returns: Win32 error from registry actions
//
//-----------------------------------------------------------------------------
DWORD
DfsRemoveRoot()
{
DWORD dwErr;
CRegKey *pcregLV;
//
// Now the volumes section
pcregLV = new CRegKey( // Open local volumes section
HKEY_LOCAL_MACHINE,
REG_KEY_LOCAL_VOLUMES);
if (pcregLV != NULL) {
dwErr = pcregLV->QueryErrorStatus();
} else {
dwErr = ERROR_OUTOFMEMORY;
}
if (dwErr == ERROR_SUCCESS) {
dwErr = pcregLV->DeleteChildren(); // Delete local volumes
delete pcregLV;
pcregLV = NULL;
if(dwErr == ERROR_SUCCESS) {
// now delete the key
dwErr = RegDeleteKey( HKEY_LOCAL_MACHINE,
REG_KEY_LOCAL_VOLUMES);
}
if (dwErr == ERROR_SUCCESS) {
//
// Recreate an empty local volumes key
//
pcregLV = new CRegKey( HKEY_LOCAL_MACHINE, REG_KEY_LOCAL_VOLUMES);
if (pcregLV != NULL) {
delete pcregLV;
pcregLV = NULL;
}
}
}
if(dwErr == ERROR_SUCCESS) {
//
// The DfsHost stuff
//
CRegKey cregVolumesDir( HKEY_LOCAL_MACHINE, &dwErr, VOLUMES_DIR );
if (dwErr != ERROR_SUCCESS) { // Unable to open volumes dir
return(dwErr);
}
dwErr = cregVolumesDir.DeleteChildren(); // Delete volumes dir
}
if(dwErr == ERROR_SUCCESS) {
dwErr = RegDeleteKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR );
}
if(pcregLV) {
delete pcregLV;
}
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: DfspCreateFtDfsDsObj
//
// Synopsis: Updates (by adding to) the Ds objects representing the FtDfs
//
// Arguments: wszServerName - Name of server we'll be adding
// wszDcName - Dc to use
// wszRootShare - Share to become the root share
// wszFtDfsName - Name of FtDfs we are creating
// ppRootList - List of FtDfs roots that need to be informed of
// the changed Ds object
//
// Returns: NTSTATUS of the call (STATUS_SUCCESS or error)
//
//-----------------------------------------------------------------------------
DWORD
DfspCreateFtDfsDsObj(
LPWSTR wszServerName,
LPWSTR wszDcName,
LPWSTR wszRootShare,
LPWSTR wszFtDfsName,
PDFSM_ROOT_LIST *ppRootList)
{
DWORD dwErr = ERROR_SUCCESS;
DWORD i, j;
WCHAR wszDfsConfigDN[MAX_PATH+1];
WCHAR wszServerShare[MAX_PATH+1];
LPWSTR wszConfigurationDN = NULL;
LDAP *pldap = NULL;
PLDAPMessage pMsg = NULL;
LDAPModW ldapModServer;
LPWSTR rgAttrs[5];
PLDAPModW rgldapMods[6];
LDAPMessage *pmsgServers;
PWCHAR *rgServers;
PWCHAR *rgNewServers;
DWORD cServers;
dwErr = DfspLdapOpen(wszDcName, &pldap, &wszConfigurationDN);
if (dwErr != ERROR_SUCCESS) {
pldap = NULL;
goto Cleanup;
}
wcscpy(wszDfsConfigDN,L"CN=");
wcscat(wszDfsConfigDN,wszFtDfsName);
wcscat(wszDfsConfigDN,L",");
wcscat(wszDfsConfigDN,wszConfigurationDN);
wcscpy(wszServerShare,L"\\\\");
wcscat(wszServerShare,wszServerName);
wcscat(wszServerShare,L"\\");
wcscat(wszServerShare,wszRootShare);
rgAttrs[0] = L"remoteServerName";
rgAttrs[1] = NULL;
if (DfsSvcLdap)
DbgPrint("DfspCreateFtDfsDsObj:ldap_search_s(%ws)\n", rgAttrs[0]);
dwErr = ldap_search_sW(
pldap,
wszDfsConfigDN,
LDAP_SCOPE_BASE,
L"(objectClass=*)",
rgAttrs,
0,
&pMsg);
DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR,
DfspCreateFtDfsDsObj_Error_ldap_search_sW,
LOGULONG(dwErr));
if (dwErr == LDAP_SUCCESS) {
//
// We are joining an existing FT Dfs. Append our server\share to it
//
pmsgServers = ldap_first_entry(pldap, pMsg);
if (pmsgServers != NULL) {
rgServers = ldap_get_valuesW(
pldap,
pmsgServers,
L"remoteServerName");
if (rgServers != NULL) {
cServers = ldap_count_valuesW( rgServers );
//
// Check that we're not adding the same server in again somehow
//
for (i = 0; i < cServers; i++) {
if (_wcsicmp(wszServerShare,rgServers[i]) == 0) {
dwErr = ERROR_DUP_NAME;
ldap_value_freeW( rgServers );
ldap_msgfree( pMsg );
pMsg = NULL;
goto Cleanup;
}
}
rgNewServers = (PWCHAR *) malloc(sizeof(LPWSTR) * (cServers+2));
if (rgNewServers != NULL) {
CopyMemory( rgNewServers, rgServers, cServers * sizeof(rgServers[0]) );
rgNewServers[cServers] = wszServerShare;
rgNewServers[cServers+1] = NULL;
ldapModServer.mod_op = LDAP_MOD_REPLACE;
ldapModServer.mod_type = L"remoteServerName";
ldapModServer.mod_vals.modv_strvals = rgNewServers;
rgldapMods[0] = &ldapModServer;
rgldapMods[1] = NULL;
if (DfsSvcLdap)
DbgPrint("DfspCreateFtDfsDsObj:ldap_modify(%ws)\n", L"remoteServerName");
dwErr = ldap_modify_sW(pldap, wszDfsConfigDN, rgldapMods);
DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR,
DfspCreateFtDfsDsObj_Error_ldap_modify_sW_2,
LOGULONG(dwErr));
if (dwErr == LDAP_ATTRIBUTE_OR_VALUE_EXISTS)
dwErr = LDAP_SUCCESS;
if (dwErr != LDAP_SUCCESS) {
dwErr = LdapMapErrorToWin32(dwErr);
} else {
dwErr = ERROR_SUCCESS;
}
free(rgNewServers);
} else {
dwErr = ERROR_OUTOFMEMORY;
}
ldap_value_freeW( rgServers );
} else {
dwErr = ERROR_OUTOFMEMORY;
}
} else {
dwErr = ERROR_OUTOFMEMORY;
}
ldap_msgfree( pMsg );
pMsg = NULL;
} else {
dwErr = LdapMapErrorToWin32(dwErr);
}
if (dwErr != ERROR_SUCCESS) {
goto Cleanup;
}
//
// Create list of other roots
//
DfspCreateRootServerList(
pldap,
wszServerName,
wszDfsConfigDN,
ppRootList);
Cleanup:
if (pMsg != NULL)
ldap_msgfree(pMsg);
if (pldap != NULL && pldap != pLdapConnection) {
if (DfsSvcLdap)
DbgPrint("DfspCreateFtDfsDsObj:ldap_unbind()\n");
ldap_unbind( pldap );
}
if (wszConfigurationDN == NULL)
free(wszConfigurationDN);
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: DfspRemoveFtDfsDsObj
//
// Synopsis: Updates (by removing from) the Ds objects representing the FtDfs
//
// Arguments: wszServerName - Name of server we'll be adding
// wszDcName - Dc to use
// wszRootShare - Share to become the root share
// wszFtDfsName - Name of FtDfs we are creating
// ppRootList - List of FtDfs roots that need to be informed of
// the changed Ds object
//
// Returns: NTSTATUS of the call (STATUS_SUCCESS or error)
//
//-----------------------------------------------------------------------------
DWORD
DfspRemoveFtDfsDsObj(
LPWSTR wszServerName,
LPWSTR wszDcName,
LPWSTR wszRootShare,
LPWSTR wszFtDfsName,
PDFSM_ROOT_LIST *ppRootList)
{
DWORD dwErr = ERROR_SUCCESS;
BOOLEAN fFoundIt = FALSE;
DWORD i, j;
WCHAR wszDfsConfigDN[MAX_PATH+1];
WCHAR wszServerShare[MAX_PATH+1];
LPWSTR wszConfigurationDN = NULL;
LDAP *pldap = NULL;
PLDAPMessage pMsg = NULL;
LDAPModW ldapModServer;
LPWSTR rgAttrs[5];
PLDAPModW rgldapMods[6];
LDAPMessage *pmsgServers;
PWCHAR *rgServers;
PWCHAR *rgNewServers;
DWORD cServers;
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfspRemoveFtDfsDsObj(%ws,%ws,%ws,%ws)\n",
wszServerName,
wszDcName,
wszRootShare,
wszFtDfsName);
#endif
dwErr = DfspLdapOpen(wszDcName, &pldap, &wszConfigurationDN);
if (dwErr != ERROR_SUCCESS) {
goto Cleanup;
}
//
// Search for the FtDfs object
//
wcscpy(wszDfsConfigDN,L"CN=");
wcscat(wszDfsConfigDN,wszFtDfsName);
wcscat(wszDfsConfigDN,L",");
wcscat(wszDfsConfigDN,wszConfigurationDN);
wcscpy(wszServerShare,L"\\\\");
wcscat(wszServerShare,wszServerName);
wcscat(wszServerShare,L"\\");
wcscat(wszServerShare,wszRootShare);
rgAttrs[0] = L"remoteServerName";
rgAttrs[1] = NULL;
if (DfsSvcLdap)
DbgPrint("DfspRemoveFtDfsDsObj:ldap_search_s(%ws)\n", rgAttrs[0]);
dwErr = ldap_search_sW(
pldap,
wszDfsConfigDN,
LDAP_SCOPE_BASE,
L"(objectClass=*)",
rgAttrs,
0,
&pMsg);
DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR,
DfspRemoveFtDfsDsObj_Error_ldap_search_sW,
LOGULONG(dwErr));
if (dwErr != LDAP_SUCCESS) {
dwErr = LdapMapErrorToWin32(dwErr);
goto Cleanup;
}
dwErr = ERROR_SUCCESS;
//
// We found a Dfs object to update
//
pmsgServers = ldap_first_entry(pldap, pMsg);
if (pmsgServers != NULL) {
rgServers = ldap_get_valuesW(
pldap,
pmsgServers,
L"remoteServerName");
if (rgServers != NULL) {
cServers = ldap_count_valuesW( rgServers );
rgNewServers = (PWCHAR *)malloc(sizeof(LPWSTR) * (cServers+1));
if (rgNewServers != NULL) {
for (i = j = 0; i < cServers; i += 1) {
if (_wcsicmp(wszServerShare, rgServers[i]) == 0) {
fFoundIt = TRUE;
continue;
}
rgNewServers[j++] = rgServers[i];
}
rgNewServers[j] = NULL;
if (j > 0 && fFoundIt == TRUE) {
ldapModServer.mod_op = LDAP_MOD_REPLACE;
ldapModServer.mod_type = L"remoteServerName";
ldapModServer.mod_vals.modv_strvals = rgNewServers;
rgldapMods[0] = &ldapModServer;
rgldapMods[1] = NULL;
if (DfsSvcLdap)
DbgPrint("DfspRemoveFtDfsDsObj:ldap_modify(%ws)\n", L"remoteServerName");
dwErr = ldap_modify_sW(pldap, wszDfsConfigDN, rgldapMods);
DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR,
DfspRemoveFtDfsDsObj_Error_ldap_modify_sW,
LOGULONG(dwErr));
if (dwErr != LDAP_SUCCESS) {
dwErr = LdapMapErrorToWin32(dwErr);
} else {
dwErr = ERROR_SUCCESS;
}
}
free(rgNewServers);
} else {
dwErr = ERROR_OUTOFMEMORY;
}
ldap_value_freeW( rgServers );
} else {
dwErr = ERROR_OUTOFMEMORY;
}
} else {
dwErr = ERROR_OUTOFMEMORY;
}
if (pMsg != NULL) {
ldap_msgfree( pMsg );
pMsg = NULL;
}
if (fFoundIt == FALSE) {
dwErr = ERROR_OBJECT_NOT_FOUND;
goto Cleanup;
}
if (dwErr != ERROR_SUCCESS) {
goto Cleanup;
}
//
// Create list of other roots
//
DfspCreateRootServerList(
pldap,
wszServerName,
wszDfsConfigDN,
ppRootList);
Cleanup:
if (pMsg != NULL)
ldap_msgfree( pMsg );
if (pldap != NULL && pldap != pLdapConnection) {
if (DfsSvcLdap)
DbgPrint("DfspRemoveFtDfsDsObj:ldap_unbind()\n");
ldap_unbind( pldap );
}
if (wszConfigurationDN != NULL)
free(wszConfigurationDN);
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfspRemoveFtDfsDsObj returning %d\n", dwErr);
#endif
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: DfspCreateRootServerList
//
// Synopsis: Creates a list of root which have to be informed of the change
// to the Ds object
// tells them which DC to go to for the latest blob.
//
// Arguments: pldap -- Ldap handle to use
// wszServerName - Name of server to skip
// wszDfsConfigDN - The DN to use
// ppRootList - List of FtDfs roots that need to be informed of
// the changed Ds object
//
// Returns: NTSTATUS of the call (STATUS_SUCCESS or error)
//
//-----------------------------------------------------------------------------
DWORD
DfspCreateRootServerList(
IN LDAP *pldap,
IN LPWSTR wszServerName,
IN LPWSTR wszDfsConfigDN,
IN PDFSM_ROOT_LIST *ppRootList)
{
DWORD dwErr = ERROR_SUCCESS;
DWORD cServers;
DWORD cRoots;
DWORD i;
PDFSM_ROOT_LIST pRootList = NULL;
ULONG Size = 0;
WCHAR *pWc;
PLDAPMessage pMsg = NULL;
LDAPMessage *pmsgServers;
LPWSTR rgAttrs[5];
PWCHAR *rgServers = NULL;
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfspCreateRootServerList(%ws,%ws)\n",
wszServerName,
wszDfsConfigDN);
#endif
//
// Search for the FtDfs object
//
rgAttrs[0] = L"remoteServerName";
rgAttrs[1] = NULL;
if (DfsSvcLdap)
DbgPrint("DfspCreateRootServerList:ldap_search_s(%ws)\n", rgAttrs[0]);
dwErr = ldap_search_sW(
pldap,
wszDfsConfigDN,
LDAP_SCOPE_BASE,
L"(objectClass=*)",
rgAttrs,
0,
&pMsg);
DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR,
DfspCreateRootServerList_Error_ldap_search_sW,
LOGULONG(dwErr));
if (dwErr != ERROR_SUCCESS) {
dwErr = LdapMapErrorToWin32(dwErr);
goto Cleanup;
}
dwErr = ERROR_SUCCESS;
pmsgServers = ldap_first_entry(pldap, pMsg);
if (pmsgServers != NULL) {
rgServers = ldap_get_valuesW(
pldap,
pmsgServers,
L"remoteServerName");
if (rgServers != NULL) {
cServers = ldap_count_valuesW( rgServers );
for (cRoots = i = 0; i < cServers; i++) {
if (wcslen(rgServers[i]) < 3 ||
rgServers[i][0] != UNICODE_PATH_SEP ||
_wcsnicmp(wszServerName, &rgServers[i][2], wcslen(wszServerName)) == 0
) {
continue;
}
Size += (wcslen(rgServers[i]) + 1) * sizeof(WCHAR);
cRoots++;
}
Size += FIELD_OFFSET(DFSM_ROOT_LIST,Entry[cRoots+1]);
pRootList = (PDFSM_ROOT_LIST)MIDL_user_allocate(Size);
if (pRootList != NULL) {
RtlZeroMemory(pRootList, Size);
pRootList->cEntries = cRoots;
pWc = (WCHAR *)&pRootList->Entry[cRoots+1];
for (cRoots = i = 0; i < cServers; i++) {
if (wcslen(rgServers[i]) < 3 ||
rgServers[i][0] != UNICODE_PATH_SEP ||
_wcsnicmp(wszServerName, &rgServers[i][2], wcslen(wszServerName)) == 0
) {
continue;
}
pWc = (WCHAR *)MIDL_user_allocate((wcslen(rgServers[i]) + 1) * sizeof(WCHAR));
pRootList->Entry[cRoots].ServerShare = pWc;
wcscpy(pRootList->Entry[cRoots++].ServerShare, rgServers[i]);
}
*ppRootList = pRootList;
} else {
dwErr = ERROR_OUTOFMEMORY;
}
} else {
dwErr = ERROR_OUTOFMEMORY;
}
} else {
dwErr = ERROR_OUTOFMEMORY;
}
Cleanup:
if (rgServers != NULL)
ldap_value_freeW(rgServers);
if (pMsg != NULL)
ldap_msgfree( pMsg );
#if DBG
if (DfsSvcVerbose) {
DbgPrint("DfspCreateRootServerList dwErr=%d\n", dwErr);
if (dwErr == NO_ERROR) {
for (i = 0; i < pRootList->cEntries; i++)
DbgPrint("[%d][%ws]\n", i, pRootList->Entry[i].ServerShare);
}
}
#endif
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: DfspCreateRootList
//
// Synopsis: Helper for adding/removing jp's, really a wrapper for
// DfspCreateRootServerList
//
// Arguments: DfsEntryPath - Path (of form \\domainname\ftdfsname)
// DcName - Dc name to be used
// ppRootList - Pointer to arg for results
//
// Returns: [ERROR_SUCCESS] -- Successfully returning list
//
// [ERROR_NOT_ENOUGH_MEMORY] -- Unable to allocate list
//
// [??] - From ldap open/bind, etc.
//
//-----------------------------------------------------------------------------
DWORD
DfspCreateRootList(
IN LPWSTR DfsEntryPath,
IN LPWSTR DcName,
IN PDFSM_ROOT_LIST *ppRootList)
{
ULONG start, end;
DWORD dwErr = ERROR_SUCCESS;
WCHAR wszDfsConfigDN[MAX_PATH+1];
WCHAR wszFtDfsName[MAX_PATH+1];
WCHAR wszComputerName[MAX_PATH+1];
LPWSTR wszConfigurationDN = NULL;
LDAP *pldap = NULL;
LPWSTR rgAttrs[5];
DFS_NAME_CONVENTION NameType;
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfspCreateRootList(%ws,%ws)\n",
DfsEntryPath,
DcName);
#endif
if (DfsEntryPath == NULL || DcName == NULL) {
dwErr = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
NameType = (ulDfsManagerType == DFS_MANAGER_FTDFS) ? DFS_NAMETYPE_DNS : DFS_NAMETYPE_EITHER;
dwErr = GetDomAndComputerName( NULL, wszComputerName, &NameType);
if (dwErr != ERROR_SUCCESS) {
dprintf((
DEB_ERROR,
"Win32 Error %d getting Domain/Computer name\n", dwErr));
goto Cleanup;
}
//
// Extract the ftdfs name from the DfsEntryPath
//
for (start = 1;
DfsEntryPath[start] != UNICODE_PATH_SEP && DfsEntryPath[start] != UNICODE_NULL;
start++) {
NOTHING;
}
if (DfsEntryPath[start] == UNICODE_PATH_SEP)
start++;
for (end = start;
DfsEntryPath[end] != UNICODE_PATH_SEP && DfsEntryPath[end] != UNICODE_NULL;
end++) {
NOTHING;
}
if (DfsEntryPath[start] == UNICODE_PATH_SEP)
end--;
if (start >= end) {
ERROR_INVALID_PARAMETER;
}
RtlZeroMemory(wszFtDfsName, sizeof(wszFtDfsName));
RtlCopyMemory(wszFtDfsName, &DfsEntryPath[start], (end - start) * sizeof(WCHAR));
#if DBG
if (DfsSvcVerbose)
DbgPrint("wszFtDfsName=[%ws]\n", wszFtDfsName);
#endif
//
// Open & bind to the ds
//
dwErr = DfspLdapOpen(DcName, &pldap, &wszConfigurationDN);
if (dwErr != ERROR_SUCCESS) {
goto Cleanup;
}
//
// Search for the FtDfs object
//
wcscpy(wszDfsConfigDN,L"CN=");
wcscat(wszDfsConfigDN,wszFtDfsName);
wcscat(wszDfsConfigDN,L",");
wcscat(wszDfsConfigDN,wszConfigurationDN);
//
// Create the list of roots
//
dwErr = DfspCreateRootServerList(
pldap,
wszComputerName,
wszDfsConfigDN,
ppRootList);
Cleanup:
if (pldap != NULL && pldap != pLdapConnection) {
if (DfsSvcLdap)
DbgPrint("DfspCreateRootList:ldap_unbind()\n");
ldap_unbind( pldap );
}
if (wszConfigurationDN != NULL)
free(wszConfigurationDN);
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfspCreateRootList returning %d\n", dwErr);
#endif
return dwErr;
}
//+----------------------------------------------------------------------------
//
// Function: DfspLdapOpen
//
// Synopsis: Open ldap storage and returns the object name of the
// Dfs-Configuration object.
//
// Arguments: DfsEntryPath - wszDcName - Dc name to be used
// ppldap -- pointer to pointer to ldap obj, filled in on success
// pwszObjectName -- pointer to LPWSTR for name of dfs-config object
//
// Returns: [ERROR_SUCCESS] -- Successfully returning list
//
// [??] - From ldap open/bind, etc.
//
//-----------------------------------------------------------------------------
DWORD
DfspLdapOpen(
LPWSTR wszDcName,
LDAP **ppldap,
LPWSTR *pwszObjectName)
{
DWORD dwErr = ERROR_SUCCESS;
DWORD i;
ULONG Size;
PLDAPMessage pMsg = NULL;
LDAP *pldap = NULL;
LPWSTR rgAttrs[5];
if ( ppldap == NULL || pwszObjectName == NULL) {
dwErr = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfspLdapOpen(%ws,0x%x)\n", wszDcName,*ppldap);
#endif
//
// We must be given either a DC name or an ldap connection. If neither, then
// return an error.
//
if (*ppldap == NULL && wszDcName == NULL) {
dwErr = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
//
// If we were given an ldap connection, but no DC name, then we just want
// the name of the dfs config object.
//
if (wszDcName == NULL) {
pldap = *ppldap;
goto GetConfigObject;
}
//
// We were given a DC name and possibly an ldap connection.
//
if (*ppldap == NULL || pLdapConnection == NULL || pwszDSMachineName == NULL) {
if (pLdapConnection != NULL &&
pwszDSMachineName != NULL &&
wszDcName != NULL &&
wcscmp(pwszDSMachineName, wszDcName) == 0) {
pldap = pLdapConnection;
dwErr = ERROR_SUCCESS;
} else {
if (DfsSvcLdap)
DbgPrint("DfspLdapOpen:ldap_init(%ws)\n", wszDcName);
pldap = ldap_initW(wszDcName, LDAP_PORT);
if (pldap == NULL) {
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfspLdapOpen:ldap_init failed\n");
#endif
LdapGetLastError();
dwErr = ERROR_INVALID_NAME;
goto Cleanup; // added to prevent error masking!!
}
dwErr = ldap_set_option(pldap, LDAP_OPT_AREC_EXCLUSIVE, LDAP_OPT_ON);
if (dwErr != LDAP_SUCCESS) {
dprintf((
DEB_ERROR,
"ldap_set_option failed with ldap error %d\n", dwErr));
pldap = NULL;
goto Cleanup;
}
if (DfsSvcLdap)
DbgPrint("DfspLdapOpen:ldap_bind()\n");
dwErr = ldap_bind_s(pldap, NULL, NULL, LDAP_AUTH_SSPI);
DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR,
DfspLdapOpen_Error_ldap_bind_s,
LOGULONG(dwErr));
if (dwErr != LDAP_SUCCESS) {
#if DBG
if (DfsSvcVerbose)
DbgPrint("ldap_bind_s failed with ldap error %d\n", dwErr);
#endif
pldap = NULL;
dwErr = LdapMapErrorToWin32(dwErr);
goto Cleanup;
}
if (DfsSvcLdap)
DbgPrint("DfspLdapOpen:pLdapConnection set to %ws\n", wszDcName);
if (pLdapConnection != NULL)
ldap_unbind(pLdapConnection);
pLdapConnection = pldap;
pwszDSMachineName = wszDSMachineName;
wcscpy(pwszDSMachineName, wszDcName);
if (DfsSvcLdap)
DbgPrint("DfspLdapOpen:pLdapConnection:0x%x\n", pLdapConnection);
}
} else {
pldap = *ppldap;
}
//
// Get attribute "defaultNameContext" containing name of entry we'll be
// using for our DN
//
GetConfigObject:
if (gConfigurationDN == NULL) {
rgAttrs[0] = L"defaultnamingContext";
rgAttrs[1] = NULL;
if (DfsSvcLdap)
DbgPrint("DfspLdapOpen:ldap_search_s(%ws)\n", rgAttrs[0]);
dwErr = ldap_search_sW(
pldap,
L"",
LDAP_SCOPE_BASE,
L"(objectClass=*)",
rgAttrs,
0,
&pMsg);
DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR,
DfspLdapOpen_Error_ldap_search_sW,
LOGULONG(dwErr));
if (dwErr == LDAP_SUCCESS) {
PLDAPMessage pEntry = NULL;
PWCHAR *rgszNamingContexts = NULL;
DWORD i, cNamingContexts;
dwErr = ERROR_SUCCESS;
if ((pEntry = ldap_first_entry(pldap, pMsg)) != NULL &&
(rgszNamingContexts = ldap_get_valuesW(pldap, pEntry, rgAttrs[0])) != NULL &&
(cNamingContexts = ldap_count_valuesW(rgszNamingContexts)) > 0) {
gConfigurationDN = (LPWSTR)malloc((wcslen(*rgszNamingContexts)+1) * sizeof(WCHAR));
if (gConfigurationDN == NULL)
dwErr = ERROR_OUTOFMEMORY;
else
wcscpy( gConfigurationDN, *rgszNamingContexts );
} else {
dwErr = ERROR_UNEXP_NET_ERR;
}
if (rgszNamingContexts != NULL)
ldap_value_freeW( rgszNamingContexts );
} else {
dwErr = LdapMapErrorToWin32(dwErr);
}
if (dwErr != ERROR_SUCCESS) {
#if DBG
if (DfsSvcVerbose)
DbgPrint("Unable to find Configuration naming context\n");
#endif
goto Cleanup;
}
}
//
// Create string with full object name
//
Size = wcslen(DfsConfigContainer) * sizeof(WCHAR) +
sizeof(WCHAR) +
wcslen(gConfigurationDN) * sizeof(WCHAR) +
sizeof(WCHAR);
*pwszObjectName = (LPWSTR)malloc(Size);
if (*pwszObjectName == NULL) {
dwErr = ERROR_OUTOFMEMORY;
goto Cleanup;
}
wcscpy(*pwszObjectName,DfsConfigContainer);
wcscat(*pwszObjectName,L",");
wcscat(*pwszObjectName,gConfigurationDN);
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfspLdapOpen:object name=[%ws]\n", *pwszObjectName);
#endif
Cleanup:
//
// If we had an error and we check if the ldap connection was passed in.
// If not, and it is not pLdapConnection, close it.
//
if (dwErr != ERROR_SUCCESS &&
pldap != NULL &&
pldap != pLdapConnection &&
*ppldap == NULL) {
if (DfsSvcLdap)
DbgPrint("DfspLdapOpen:ldap_unbind()\n");
ldap_unbind( pldap );
pldap = NULL;
}
if (pMsg != NULL)
ldap_msgfree(pMsg);
if (*ppldap == NULL) {
*ppldap = pldap;
}
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfspLdapOpen:returning %d\n", dwErr);
#endif
return( dwErr );
}