windows-nt/Source/XPSP1/NT/base/fs/dfs/dfsm/server/dfsminit.cxx

1719 lines
40 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+----------------------------------------------------------------------------
//
// Copyright (C) 1995, Microsoft Corporation
//
// File: dfsminit.cxx
//
// Contents: Initialization code for Dfs Manager service.
//
// Classes:
//
// Functions: DfsManager --
// DfsInitGlobals --
// InitializeDfsManager --
// InitializeVolumeObject --
// DfsHandleKnowledgeInconsistency --
//
//-----------------------------------------------------------------------------
//#include <ntos.h>
//#include <ntrtl.h>
//#include <nturtl.h>
//#include <dfsfsctl.h>
//#include <windows.h>
#include <headers.hxx>
#pragma hdrstop
#include <dfsfsctl.h> // For EA_NAME_OPENIFJP
#include <dfsmsrv.h> // For public function
#include <clusapi.h>
#include <resapi.h>
#include <winldap.h>
#include "cdfsvol.hxx" // prototypes
#include "localvol.hxx"
#include "security.hxx"
#include "dsgetdc.h"
#include "setup.hxx"
#include "dfsmwml.h"
extern "C"
DWORD
DfsGetFtServersFromDs(
PLDAP pLDAP,
LPWSTR wszDomainName,
LPWSTR wszDfsName,
LPWSTR **List);
DWORD
DfspGetPdc(void);
//
// Debug variables
//
//WMILIB_REG_STRUCT DfsRtlWmiReg;
///GUID DfsmRtlTraceGuid = { // 08fbc600-67ac-4ae4-9f22-c51a4f82f6c9
// 0x08fbc600, 0x67ac, 0x4ae4,
// {
// 0x9f, 0x22, 0xc5, 0x1a, 0x4f, 0x82, 0xf6, 0xc9
// }
//};
//WML_DATA wml;
DECLARE_INFOLEVEL(IDfsVol)
//
// Global variables.
//
CRITICAL_SECTION globalCritSec;
ULONG ulDfsManagerType;
WCHAR wszComputerName[MAX_PATH];
LPWSTR pwszComputerName = NULL;
WCHAR wszDomainName[MAX_PATH];
LPWSTR pwszDomainName = NULL;
WCHAR wszDfsRootName[MAX_PATH];
LPWSTR pwszDfsRootName = NULL;
WCHAR wszDSMachineName[MAX_PATH];
LPWSTR pwszDSMachineName = NULL;
//
// Contains the name of the FtDfs, if we are an FtDfs root
//
WCHAR wszFtDfsName[MAX_PATH];
LPWSTR pwszFtDfsName = NULL;
//
// If an FtDfs, this is the ldap connection we're using
//
PLDAP pLdapConnection = NULL;
ULONG GTimeout = 0;
extern "C" {
ULONG DfsSvcVerbose = 0;
ULONG DfsSvcLdap = 0;
ULONG DfsEventLog = 0;
ULONG DfsDnsConfig = 0;
}
BOOLEAN NetDfsInitDone = FALSE;
HANDLE hSyncThread = NULL;
HANDLE hSyncEvent = NULL;
HANDLE hFrsSyncEvent = NULL;
DWORD dwFrsSyncIntervalInMs = 1000 * 60; // 1 minute by default
DWORD dwSyncIntervalInMs = 1000 * 60 * 60; // 1 hour by default
DWORD dwSyncThreadId;
ULONG DcLockIntervalInMs = 1000 * 60 * 60 * 2; // 2 hours by default
CStorageDirectory *pDfsmStorageDirectory = NULL;
CSites *pDfsmSites = NULL;
#if (DBG == 1) || (_CT_TEST_HOOK == 1)
RECOVERY_BREAK_POINT gRecoveryBkptInfo;
#endif
//
// The name of the Dfs configuration container
//
WCHAR DfsConfigContainer[] = L"CN=Dfs-Configuration,CN=System";
LPWSTR gConfigurationDN = NULL;
//
// Useful EA Buffer for opening Junction Points
//
CHAR EaBuffer[ sizeof(FILE_FULL_EA_INFORMATION) + sizeof(EA_NAME_OPENIFJP) ];
PFILE_FULL_EA_INFORMATION pOpenIfJPEa = (PFILE_FULL_EA_INFORMATION) EaBuffer;
ULONG cbOpenIfJPEa = sizeof(EaBuffer);
DWORD
InitializeVolumeObject(
PWSTR pwszVolName,
BOOLEAN bInitVol,
BOOLEAN SyncRemoteServerName=FALSE);
DWORD
InitializeDfsManager(void);
DWORD
InitializeNetDfsInterface(void);
DWORD
DfsManagerStartDSSync();
DWORD
DfsManagerDSSyncThread(
PVOID Context);
DWORD
GetSyncInterval();
ULONG
GetDcLockInterval();
DWORD
GetEntryTimeout();
VOID
GetDebugSwitches();
VOID
GetEventLogSwitches();
VOID
GetConfigSwitches();
DWORD
DfspGetFtDfsName();
//+----------------------------------------------------------------------------
//
// Function: DfsManager
//
// Synopsis: Entry procedure for the main Dfs Manager service thread.
// Initializes the Dfs Manager structures, creates the RPC
// threads that will wait around listening for admin operation
// calls, and lastly, creates a thread to monitor Knowledge
// Sync calls from the driver.
//
// Arguments: [wszRootName] -- Name of dfs root for which this Dfs Manager
// is being instantiated.
// [dwType] -- Type of Dfs Manager being instantiated -
// DFS_MANAGER_SERVER or DFS_MANAGER_FTDFS
//
// Returns: [ERROR_SUCCESS] -- If Dfs Manager started correctly.
//
// [ERROR_OUTOFMEMORY] -- If globals could not be allocated.
//
// Error from reading the Dfs Volume Objects.
//
// Win32 error from registering the RPC interface.
//
// Win32 error from creating the knowledge sync thread.
//
//-----------------------------------------------------------------------------
DWORD
DfsManager(
LPWSTR wszRootName,
DWORD dwType)
{
HANDLE hthreadSync;
DWORD idThread;
DWORD dwErr = ERROR_SUCCESS;
HKEY hkey;
DFS_NAME_CONVENTION NameType;
//
// Initialize the global data structures of Dfs Manager...
//
IDfsVolInlineDebOut((DEB_TRACE, "DfsManager(%ws,0x%x)\n", wszRootName, dwType));
if (dwType == DFS_MANAGER_FTDFS) {
dwErr = DfsInitGlobals(wszRootName, dwType);
} else {
NameType = DFS_NAMETYPE_EITHER;
dwErr = GetDomAndComputerName(NULL, wszComputerName, &NameType);
dwErr = DfsInitGlobals(wszComputerName, dwType);
}
if (dwErr != ERROR_SUCCESS) {
IDfsVolInlineDebOut((DEB_ERROR, "DfsInitGlobals failed %08lx\n", dwErr));
return(dwErr);
}
//
// Initialize the NetDfs RPC interface...
//
dwErr = InitializeNetDfsInterface();
if (dwErr != ERROR_SUCCESS) {
IDfsVolInlineDebOut((DEB_ERROR, "InitializeNetDfsInterface failed %08lx\n", dwErr));
return dwErr;
}
//
// Read in all the Dfs volume objects and initialize them
//
ENTER_DFSM_OPERATION;
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
if (dwErr == ERROR_SUCCESS) {
RegCloseKey( hkey );
DfsmStopDfs();
DfsmResetPkt();
DfsmInitLocalPartitions();
DfsmMarkStalePktEntries();
InitializeVolumeObject( DOMAIN_ROOT_VOL, TRUE, (ulDfsManagerType == DFS_MANAGER_FTDFS)?TRUE:FALSE );
DfsmFlushStalePktEntries();
}
DfsmStartDfs();
DfsmPktFlushCache();
EXIT_DFSM_OPERATION;
if (dwErr != ERROR_SUCCESS)
{
IDfsVolInlineDebOut((DEB_ERROR, "InitializeDfsManager failed %08lx\n", dwErr));
return dwErr;
}
if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
//
// Start the thread that does the DS sync
//
dwErr = DfsManagerStartDSSync();
if (dwErr != ERROR_SUCCESS) {
IDfsVolInlineDebOut((DEB_ERROR, "DfsManagerStartDSSync failed %08lx\n", dwErr));
return(dwErr);
}
}
IDfsVolInlineDebOut((DEB_TRACE, "DfsManager exit\n"));
return ERROR_SUCCESS;
} // DfsManager
DWORD
ClusCallBackFunction(
HRESOURCE hSelf,
HRESOURCE hResource,
LPVOID lpNull)
{
DWORD Value = 0;
DWORD dwStatus = ERROR_INVALID_HANDLE;
HKEY hKey = NULL;
HKEY hParamKey = NULL;
WCHAR wszClusterName[MAX_PATH];
ULONG cSize = MAX_PATH;
hKey = GetClusterResourceKey(hResource, KEY_READ);
if (hKey != NULL) {
dwStatus = ClusterRegOpenKey( hKey, L"Parameters", KEY_READ, &hParamKey );
DFSM_TRACE_ERROR_HIGH(dwStatus, ALL_ERROR, ClusCallBackFunction_Error_ClusterRegOpenKey,
LOGSTATUS(dwStatus));
}
if (dwStatus != ERROR_SUCCESS)
goto ExitWithStatus;
ResUtilGetDwordValue(hParamKey, L"IsDfsRoot", &Value, 0);
if (Value == 1
&&
GetClusterResourceNetworkName(hResource, wszClusterName, &cSize) == TRUE
) {
#if DBG
if (DfsSvcVerbose)
DbgPrint("ClusCallBackFunction: ClusterName = [%ws]\n", wszClusterName);
#endif
wcscpy(wszDfsRootName, wszClusterName);
wcscpy(wszComputerName, wszClusterName);
} else {
#if DBG
if (DfsSvcVerbose)
DbgPrint("ClusCallBackFunction: Not a root on a cluster.\n");
#endif
}
ExitWithStatus:
if (hKey != NULL)
ClusterRegCloseKey(hKey);
if (hParamKey != NULL)
ClusterRegCloseKey(hParamKey);
return dwStatus;
}
//+----------------------------------------------------------------------------
//
// Function: DfsInitGlobals
//
// Synopsis: Initialize the Dfs Manager globals.
//
// Arguments:
//
// Returns:
//
//-----------------------------------------------------------------------------
extern "C" DWORD
DfsInitGlobals(
LPWSTR pwszRootName,
DWORD dwType)
{
static BOOLEAN fInitDone = FALSE;
DWORD dwErr = ERROR_SUCCESS;
ULONG ulSize = MAX_PATH*sizeof(WCHAR);
DFS_NAME_CONVENTION NameType;
IDfsVolInlineDebOut((DEB_TRACE, "DfsInitGlobals(%ws, %x)\n", pwszRootName, dwType));
//
// Only do init once.
//
if ( !fInitDone ) {
DebugInitialize();
#if DBG
GetDebugSwitches();
if (DfsSvcVerbose)
DbgPrint("DfsInitGlobals(%ws,%d)\n", pwszRootName, dwType);
#endif
GetEventLogSwitches();
GetConfigSwitches();
pwszDSMachineName = NULL;
GTimeout = GetEntryTimeout();
DcLockIntervalInMs = GetDcLockInterval();
ulDfsManagerType = dwType;
pOpenIfJPEa->NextEntryOffset = 0;
pOpenIfJPEa->Flags = 0;
pOpenIfJPEa->EaNameLength = strlen(EA_NAME_OPENIFJP);
pOpenIfJPEa->EaValueLength = 0;
strcpy(pOpenIfJPEa->EaName, EA_NAME_OPENIFJP);
//
// Must enforce exclusivity before the service starts.
//
InitializeCriticalSection(&globalCritSec);
#if (DBG == 1) || (_CT_TEST_HOOK == 1)
gRecoveryBkptInfo.BreakPt = 0xFFFFFFFF;
gRecoveryBkptInfo.pwszApiBreak = NULL;
#endif
wcscpy(wszDfsRootName, pwszRootName);
pwszDfsRootName = wszDfsRootName;
//
// Get computer and domain names
//
NameType = (ulDfsManagerType == DFS_MANAGER_FTDFS) ? DFS_NAMETYPE_DNS : DFS_NAMETYPE_EITHER;
dwErr = GetDomAndComputerName(wszDomainName, wszComputerName, &NameType);
if (dwErr == NERR_Success) {
pwszDomainName = wszDomainName;
pwszComputerName = wszComputerName;
} else {
pwszDomainName = NULL;
pwszComputerName = NULL;
}
//
// Figure out the root of the namespace.
// The root name is the cluster name on clusters, if
// this is a machine-based Dfs.
//
if (dwErr == NERR_Success && ulDfsManagerType == DFS_MANAGER_SERVER) {
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfsInitGlobals: calling ResUtilEnumResources()\n");
#endif
ResUtilEnumResources(NULL,
L"File Share",
ClusCallBackFunction,
NULL);
}
//
// Initialize the ACLs and other global security datastructures needed
// for Access Validation
//
if (dwErr == ERROR_SUCCESS) {
if (DfsInitializeSecurity())
dwErr = ERROR_SUCCESS;
else
dwErr = ERROR_UNEXP_NET_ERR;
}
//
// Initialize the LDAP storage
//
if (dwErr == ERROR_SUCCESS && ulDfsManagerType == DFS_MANAGER_FTDFS) {
dwErr = InitializeLdapStorage(
wszDfsRootName);
}
//
// Initialize the CSites class/storage
//
if (dwErr == ERROR_SUCCESS) {
if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
pDfsmSites = new CSites(LDAP_VOLUMES_DIR SITE_ROOT, &dwErr);
} else {
pDfsmSites = new CSites(VOLUMES_DIR SITE_ROOT, &dwErr);
}
if (pDfsmSites != NULL) {
if (dwErr != ERROR_SUCCESS) {
delete pDfsmSites;
pDfsmSites = NULL;
dwErr = ERROR_OUTOFMEMORY;
}
} else {
dwErr = ERROR_OUTOFMEMORY;
}
}
//
// Initialize the Dfs Manager Storage Directory
//
if (dwErr == ERROR_SUCCESS ) {
pDfsmStorageDirectory = new CStorageDirectory( &dwErr );
if (pDfsmStorageDirectory != NULL) {
if (dwErr == ERROR_SUCCESS) {
fInitDone = TRUE;
} else {
delete pDfsmStorageDirectory;
pDfsmStorageDirectory = NULL;
delete pDfsmSites;
pDfsmSites = NULL;
fInitDone = FALSE;
}
} else {
delete pDfsmSites;
pDfsmSites = NULL;
fInitDone = FALSE;
dwErr = ERROR_OUTOFMEMORY;
}
}
}
IDfsVolInlineDebOut((DEB_TRACE, "DfsInitGlobals() exit\n"));
return dwErr;
} // DfsInitGlobals
//+----------------------------------------------------------------------------
//
// Function: DfsReinitGlobals
//
// Synopsis: ReInitialize the Dfs Manager globals.
//
// Arguments:
//
// Returns:
//
//-----------------------------------------------------------------------------
DWORD
DfsReInitGlobals(
LPWSTR pwszRootName,
DWORD dwType)
{
DWORD dwErr = ERROR_SUCCESS;
ULONG ulSize = MAX_PATH*sizeof(WCHAR);
DFS_NAME_CONVENTION NameType;
IDfsVolInlineDebOut((DEB_TRACE, "DfsReInitGlobals(%ws, %x)\n", pwszRootName, dwType));
#if DBG
GetDebugSwitches();
if (DfsSvcVerbose)
DbgPrint("DfsReInitGlobals(%ws, %d)\n", pwszRootName, dwType);
#endif
GetEventLogSwitches();
GetConfigSwitches();
//
// Get rid of Dfs Manager storage & site info
//
if (pDfsmStorageDirectory != NULL) {
delete pDfsmStorageDirectory;
pDfsmStorageDirectory = NULL;
}
if (pDfsmSites != NULL) {
delete pDfsmSites;
pDfsmSites = NULL;
}
//
// Get rid of Ldap storage
//
UnInitializeLdapStorage();
ulDfsManagerType = dwType;
wcscpy(wszDfsRootName, pwszRootName);
pwszDfsRootName = wszDfsRootName;
//
// Get computer and domain names
//
NameType = (ulDfsManagerType == DFS_MANAGER_FTDFS) ? DFS_NAMETYPE_DNS : DFS_NAMETYPE_EITHER;
dwErr = GetDomAndComputerName(wszDomainName, wszComputerName, &NameType);
if (dwErr == NERR_Success) {
pwszDomainName = wszDomainName;
pwszComputerName = wszComputerName;
} else {
pwszDomainName = NULL;
pwszComputerName = NULL;
}
//
// Figure out the root of the namespace.
// The root name is the cluster name on clusters, if
// this is a machine-based Dfs.
//
if (dwErr == NERR_Success && ulDfsManagerType == DFS_MANAGER_SERVER) {
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfsReInitGlobals: calling ResUtilEnumResources()\n");
#endif
ResUtilEnumResources(NULL,
L"File Share",
ClusCallBackFunction,
NULL);
}
//
// Initialize the LDAP storage
//
if (dwErr == ERROR_SUCCESS && ulDfsManagerType == DFS_MANAGER_FTDFS) {
dwErr = InitializeLdapStorage(
wszDfsRootName);
}
//
// Initialize the CSites class/storage
//
if (dwErr == ERROR_SUCCESS) {
if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
pDfsmSites = new CSites(LDAP_VOLUMES_DIR SITE_ROOT, &dwErr);
} else {
pDfsmSites = new CSites(VOLUMES_DIR SITE_ROOT, &dwErr);
}
if (pDfsmSites != NULL) {
if (dwErr != ERROR_SUCCESS) {
delete pDfsmSites;
pDfsmSites = NULL;
dwErr = ERROR_OUTOFMEMORY;
}
} else {
dwErr = ERROR_OUTOFMEMORY;
}
}
//
// Initialize the Dfs Manager Storage Directory
//
if (dwErr == ERROR_SUCCESS ) {
pDfsmStorageDirectory = new CStorageDirectory( &dwErr );
if (pDfsmStorageDirectory != NULL) {
if (dwErr != ERROR_SUCCESS) {
delete pDfsmStorageDirectory;
pDfsmStorageDirectory = NULL;
delete pDfsmSites;
pDfsmSites = NULL;
}
} else {
delete pDfsmSites;
pDfsmSites = NULL;
dwErr = ERROR_OUTOFMEMORY;
}
}
if (dwType == DFS_MANAGER_FTDFS && hSyncThread == NULL) {
//
// Start the thread that does the DS sync
//
dwErr = DfsManagerStartDSSync();
if (dwErr != ERROR_SUCCESS) {
IDfsVolInlineDebOut((DEB_ERROR, "DfsManagerStartDSSync failed %08lx\n", dwErr));
return(dwErr);
}
}
IDfsVolInlineDebOut((DEB_TRACE, "DfsReInitGlobals() exit\n"));
return dwErr;
} // DfsReInitGlobals
//+------------------------------------------------------------------------
//
// Function: InitializeDfsManager
//
// Synopsis: This method initializes the PKT with the volume objects
//
// Arguments: None
//
// Returns:
//
// Notes:
//
//-------------------------------------------------------------------------
DWORD
InitializeDfsManager(void)
{
DWORD dwErr;
HKEY hkey;
GetEventLogSwitches();
GetConfigSwitches();
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
if (dwErr == ERROR_SUCCESS) {
RegCloseKey( hkey );
dwErr = InitializeVolumeObject( DOMAIN_ROOT_VOL, TRUE );
} else {
dwErr = ERROR_SUCCESS;
}
return(dwErr);
}
//+-----------------------------------------------------------------------
//
// Function: InitializeVolumeObject
//
// Synopsis: This function initializes a volume object and hence all
// objects underneath that one.
//
// Arguments: [pwszVolName] -- Volume Object's Name.
// [bInitVol] -- If TRUE call UpdatePktEntry on this object also.
//
//------------------------------------------------------------------------
DWORD
InitializeVolumeObject(
PWSTR pwszVolName,
BOOLEAN bInitVol,
BOOLEAN SyncRemoteServerName)
{
ULONG count = 0;
DWORD dwErr;
CDfsVolume *tempCDfs;
WCHAR wszVolObjName[MAX_PATH];
HANDLE PktHandle = NULL;
NTSTATUS status;
IDfsVolInlineDebOut(
(DEB_TRACE,
"InitializeVolumeObject(%ws,%d)\n",
pwszVolName, bInitVol));
#if DBG
if (DfsSvcVerbose)
DbgPrint("InitializeVolumeObject(%ws,%s)\n",
pwszVolName,
bInitVol == TRUE ? "TRUE" : "FALSE");
#endif
if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
wcscpy(wszVolObjName, LDAP_VOLUMES_DIR);
} else {
wcscpy(wszVolObjName, VOLUMES_DIR);
}
wcscat(wszVolObjName, pwszVolName);
IDfsVolInlineDebOut(
(DEB_TRACE,
"wszVolObjName=%ws\n",
wszVolObjName));
tempCDfs = new CDfsVolume();
if (tempCDfs == NULL) {
dwErr = ERROR_OUTOFMEMORY;
IDfsVolInlineDebOut((DEB_TRACE, "InitializeVolumeObject Exit\n"));
#if DBG
if (DfsSvcVerbose)
DbgPrint("InitializeVolumeObject exit %d\n", dwErr);
#endif
return dwErr;
}
dwErr = tempCDfs->LoadNoRegister(wszVolObjName, 0);
if (dwErr == ERROR_SUCCESS) {
//
// We'll be sync'ing the site table, so be sure it's ready
//
pDfsmSites->AddRef();
pDfsmSites->MarkEntriesForMerge();
//
// We have to update the PKT entry first since InitializePkt
// will not bother about that part.
//
if (bInitVol) {
status = PktOpen(&PktHandle, 0, 0, NULL);
if (!NT_SUCCESS(status))
PktHandle = NULL;
dwErr = tempCDfs->UpdatePktEntry(PktHandle);
}
if (dwErr != ERROR_SUCCESS) {
//
// We log an EVENT here since this needs admin intervention
// but we go on however.
//
IDfsVolInlineDebOut((DEB_ERROR, "Could not UpdatePkt on %ws %08lx\n",
pwszVolName, dwErr));
} else
#if DBG
if (DfsSvcVerbose)
DbgPrint("InitializevolumeObject:Calling InitializePkt\n");
#endif
if (PktHandle == NULL) {
status = PktOpen(&PktHandle, 0, 0, NULL);
if (!NT_SUCCESS(status))
PktHandle = NULL;
}
dwErr = tempCDfs->InitializePkt(PktHandle);
if (PktHandle != NULL)
PktClose(PktHandle);
#if DBG
if (DfsSvcVerbose)
DbgPrint("InitializevolumeObject:InitializePkt returned %d\n", dwErr);
#endif
//
// The site table should now be in sync
//
pDfsmSites->SyncPktSiteTable();
pDfsmSites->Release();
} else {
IDfsVolInlineDebOut((DEB_ERROR, "Unable to get to %ws %08lx\n",
pwszVolName, dwErr));
}
tempCDfs->Release();
IDfsVolInlineDebOut((DEB_TRACE, "InitializeVolumeObject Exit\n"));
#if DBG
if (DfsSvcVerbose)
DbgPrint("InitializeVolumeObject exit %d\n", dwErr);
#endif
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: InitializeNetDfsInterface
//
// Synopsis: Initializes the NetDfs RPC interface, so this Dfs Manager can
// start servicing the NetDfsXXX APIs.
//
// Arguments: None
//
// Returns: DWORD_FROM_WIN32 of the RPC status from registering the
// RPC interface.
//
//-----------------------------------------------------------------------------
DWORD
InitializeNetDfsInterface()
{
RPC_STATUS status;
LPWSTR wszProtocolSeq = L"ncacn_np";
LPWSTR wszEndPoint = L"\\pipe\\netdfs";
if (NetDfsInitDone == TRUE)
return ERROR_SUCCESS;
status = RpcServerUseProtseqEpW(
(USHORT *)wszProtocolSeq, // Named Pipe protocol
20, // Max # of calls
(USHORT *)wszEndPoint, // Name of named pipe
NULL); // Security Descriptor
DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, InitializeNetDfsInterface_Error_RpcServerUseProtseqEpW,
LOGSTATUS(status));
if (status) {
IDfsVolInlineDebOut((DEB_ERROR, "RpcServerUseProtseqEpW failed %08lx\n", status));
return(status);
}
//
// Register the DfsAdministration interface with the RPC runtime library
//
status = RpcServerRegisterIf(netdfs_ServerIfHandle, 0, 0);
DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, InitializeNetDfsInterface_Error_RpcServerRegisterIf,
LOGSTATUS(status));
if (status) {
IDfsVolInlineDebOut((DEB_ERROR, "RpcServerRegisterIf failed %08lx\n", status));
return(status);
}
//
// Wait for client calls...
//
status = RpcServerListen(
1, // Minimum # of calls
RPC_C_LISTEN_MAX_CALLS_DEFAULT, // Max calls
1); // Don't wait...
DFSM_TRACE_ERROR_HIGH(status, ALL_ERROR, InitializeNetDfsInterface_Error_RpcServerListen,
LOGSTATUS(status));
if (status) {
IDfsVolInlineDebOut((DEB_ERROR, "RpcServerListen failed %08lx\n", status));
}
if (status == ERROR_SUCCESS) {
NetDfsInitDone = TRUE;
}
return( status );
}
//+----------------------------------------------------------------------------
//
// Function: DfsManagerHandleKnowledgeInconsistency
//
// Synopsis: Routine to handle knowledge inconsistencies being reported by
// Dfs clients.
//
// Arguments: [Buffer] -- Pointer to marshalled Volume Verify Arg
// [cbMessage] -- size in bytes of pBuffer
//
// Returns: [STATUS_SUCCESS] -- Knowledge inconsistency fixed.
//
// [STATUS_UNSUCCESSFUL] -- Unable to fix Knowledge inconsistency.
// Problem has been logged to event log.
//
//-----------------------------------------------------------------------------
extern "C" NTSTATUS
DfsManagerHandleKnowledgeInconsistency(
PBYTE Buffer,
ULONG cbMessage)
{
DWORD dwErr = ERROR_SUCCESS;
NTSTATUS Status;
MARSHAL_BUFFER MarshalBuffer;
DFS_VOLUME_VERIFY_ARG arg;
PWSTR pwszVolName;
CDfsVolume *pcdfsvol;
pcdfsvol = new CDfsVolume();
if (pcdfsvol != NULL) {
MarshalBufferInitialize(&MarshalBuffer, cbMessage, Buffer);
Status = DfsRtlGet(&MarshalBuffer, &MiVolumeVerifyArg, &arg);
if (NT_SUCCESS(Status)) {
IDfsVolInlineDebOut((DEB_TRACE, "GotParameters: %ws\n", arg.ServiceName.Buffer));
dwErr = GetVolObjForPath(arg.Id.Prefix.Buffer, TRUE, &pwszVolName);
if (dwErr == ERROR_SUCCESS) {
IDfsVolInlineDebOut((DEB_TRACE, "GotVolObjName: %ws\n", pwszVolName));
dwErr = pcdfsvol->LoadNoRegister(pwszVolName, 0);
if (dwErr == ERROR_SUCCESS) {
//
// Remember that the ID actually has the serviceName.
//
dwErr = pcdfsvol->FixServiceKnowledge(arg.ServiceName.Buffer);
} else {
IDfsVolInlineDebOut((
DEB_TRACE, "Could not bind to Vol object\n"));
}
delete [] pwszVolName;
} else {
IDfsVolInlineDebOut((
DEB_TRACE, "Could not get volume objectName\n"));
}
if (arg.Id.Prefix.Buffer != NULL) {
MarshalBufferFree(arg.Id.Prefix.Buffer);
}
if (arg.ServiceName.Buffer != NULL) {
MarshalBufferFree(arg.ServiceName.Buffer);
}
if (dwErr != ERROR_SUCCESS)
Status = STATUS_UNSUCCESSFUL;
} else {
IDfsVolInlineDebOut((
DEB_TRACE,
"Error (NTSTATUS) unmarshalling Knowledge Sync Params %08lx\n",
Status));
}
pcdfsvol->Release();
} else {
Status = STATUS_UNSUCCESSFUL;
}
return(Status);
}
//+----------------------------------------------------------------------------
//
// Function: DfsManagerStartDSSync
//
// Synopsis: Starts a thread that will periodically sync up with the PKT
// in the DS. Used on FT-Dfs root servers.
//
// Arguments: None
//
// Returns: Win32 error from result of allocating necessary resources to
// do DS sync
//
//-----------------------------------------------------------------------------
DWORD
DfsManagerStartDSSync()
{
DWORD dwErr = ERROR_SUCCESS;
NTSTATUS Status;
OBJECT_ATTRIBUTES obja;
ASSERT( ulDfsManagerType == DFS_MANAGER_FTDFS );
InitializeObjectAttributes(&obja, NULL, OBJ_OPENIF, NULL, NULL);
Status = NtCreateEvent(
&hSyncEvent,
SYNCHRONIZE | EVENT_QUERY_STATE | EVENT_MODIFY_STATE,
&obja,
SynchronizationEvent,
FALSE);
if (Status == STATUS_SUCCESS) {
Status = NtCreateEvent(
&hFrsSyncEvent,
SYNCHRONIZE | EVENT_QUERY_STATE | EVENT_MODIFY_STATE,
&obja,
SynchronizationEvent,
FALSE);
}
DFSM_TRACE_ERROR_HIGH(Status, ALL_ERROR, DfsManagerStartDSSync_Error_NtCreateEvent,
LOGSTATUS(Status));
if (Status == STATUS_SUCCESS) {
hSyncThread = CreateThread(
NULL,
0,
DfsManagerDSSyncThread,
NULL,
0,
&dwSyncThreadId);
if (hSyncThread == NULL)
dwErr = GetLastError();
} else {
dwErr = GetLastError();
hSyncEvent = NULL;
}
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: DfsManagerDSSyncThread
//
// Synopsis: Periodically syncs the local metadata with the DS
//
// Arguments: [Context] -- Ignored
//
// Returns: Nothing
//
//-----------------------------------------------------------------------------
#if _MSC_FULL_VER >= 13008827
#pragma warning(push)
#pragma warning(disable:4715) // Not all control paths return (due to infinite loop)
#endif
DWORD
DfsManagerDSSyncThread(
PVOID Context)
{
DWORD dwErr;
HKEY hkey;
while (1) {
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfsManagerDSSyncThread()\n");
#endif
dwSyncIntervalInMs = GetSyncInterval();
dwErr = WaitForSingleObject(hSyncEvent, dwSyncIntervalInMs);
if (dwErr != WAIT_TIMEOUT) {
WaitForSingleObject(hFrsSyncEvent, dwFrsSyncIntervalInMs);
}
IDfsVolInlineDebOut((DEB_TRACE, "DfsManagerDSSyncThread()\n"));
if (ulDfsManagerType == DFS_MANAGER_FTDFS) {
ENTER_DFSM_OPERATION;
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
if (dwErr == ERROR_SUCCESS) {
RegCloseKey( hkey );
LdapIncrementBlob(TRUE);
dwErr = LdapDecrementBlob();
}
EXIT_DFSM_OPERATION;
}
}
return( 0 );
}
#if _MSC_FULL_VER >= 13008827
#pragma warning(pop)
#endif
//+----------------------------------------------------------------------------
//
// Function: DfspGetPdc
//
// Synopsis: Sets the global pwszDSMachineName to the PDC
//
// Arguments: None
//
// Returns: ERROR_SUCCESS or failure
//
//-----------------------------------------------------------------------------
DWORD
DfspGetPdc(void)
{
DWORD dwErr;
PDOMAIN_CONTROLLER_INFO pDCInfo;
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfspGetPdc()\n");
#endif
dwErr = DsGetDcName(
NULL, // Computer to remote to
NULL, // Domain - use local domain
NULL, // Domain Guid
NULL, // Site Guid
DS_PDC_REQUIRED | DS_FORCE_REDISCOVERY,
&pDCInfo);
DFSM_TRACE_ERROR_HIGH(dwErr, ALL_ERROR, DfspGetPdc_Error_DsGetDcName,
LOGULONG(dwErr)
);
if (dwErr == ERROR_SUCCESS) {
if (pwszDSMachineName == NULL)
pwszDSMachineName = wszDSMachineName;
wcscpy(pwszDSMachineName, &pDCInfo->DomainControllerName[2]);
NetApiBufferFree( pDCInfo );
}
#if DBG
if (DfsSvcVerbose)
DbgPrint("DfspGetPdc() returning %d\n", dwErr);
#endif
return( dwErr );
}
//+----------------------------------------------------------------------------
//
// Function: GetSyncInterval
//
// Synopsis: Returns the interval at which to sync with the DS
//
// Arguments: None
//
// Returns: Returns the interval at which to sync with the DS
//
//-----------------------------------------------------------------------------
DWORD
GetSyncInterval()
{
DWORD dwErr;
DWORD dwType;
DWORD dwIntervalInSeconds = 60 * 60;
DWORD cbData;
HKEY hkey;
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, REG_KEY_DFSSVC, &hkey );
if (dwErr == ERROR_SUCCESS) {
cbData = sizeof(dwIntervalInSeconds);
dwErr = RegQueryValueEx(
hkey,
SYNC_INTERVAL_NAME,
NULL,
&dwType,
(PBYTE) &dwIntervalInSeconds,
&cbData);
if (!(dwErr == ERROR_SUCCESS && dwType == REG_DWORD)) {
dwIntervalInSeconds = 60 * 60;
}
RegCloseKey(hkey);
}
return( dwIntervalInSeconds * 1000 );
}
//+----------------------------------------------------------------------------
//
// Function: GetDcLockInterval
//
// Synopsis: Returns the interval to lock onto a DC
//
// Arguments: None
//
// Returns: Returns the interval to lock onto a DC
//
//-----------------------------------------------------------------------------
ULONG
GetDcLockInterval()
{
DWORD dwErr;
DWORD dwType;
DWORD dwIntervalInSeconds = 60 * 60 * 2;
DWORD cbData;
HKEY hkey;
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, REG_KEY_DFSSVC, &hkey );
if (dwErr == ERROR_SUCCESS) {
cbData = sizeof(dwIntervalInSeconds);
dwErr = RegQueryValueEx(
hkey,
DCLOCK_INTERVAL_NAME,
NULL,
&dwType,
(PBYTE) &dwIntervalInSeconds,
&cbData);
if (!(dwErr == ERROR_SUCCESS && dwType == REG_DWORD)) {
dwIntervalInSeconds = 60 * 60 * 2;
}
RegCloseKey(hkey);
}
return( dwIntervalInSeconds * 1000 );
}
//+----------------------------------------------------------------------------
//
// Function: GetEntryTimeout
//
// Synopsis: Returns the timeout (in seconds) for jp's
//
// Arguments: None
//
//-----------------------------------------------------------------------------
DWORD
GetEntryTimeout()
{
DWORD dwErr;
DWORD dwType;
DWORD dwTimeoutInSeconds = DEFAULT_PKT_ENTRY_TIMEOUT;
DWORD cbData;
HKEY hkey;
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
if (dwErr == ERROR_SUCCESS) {
cbData = sizeof(dwTimeoutInSeconds);
dwErr = RegQueryValueEx(
hkey,
REG_VALUE_TIMETOLIVE,
NULL,
&dwType,
(PBYTE) &dwTimeoutInSeconds,
&cbData);
if (!(dwErr == ERROR_SUCCESS && dwType == REG_DWORD)) {
dwTimeoutInSeconds = DEFAULT_PKT_ENTRY_TIMEOUT;
}
RegCloseKey(hkey);
}
return( dwTimeoutInSeconds );
}
//+----------------------------------------------------------------------------
//
// Function: DfspGetFtDfsName
//
// Synopsis: Gets the FtDfs name from the registry
//
// Arguments: None
//
//-----------------------------------------------------------------------------
DWORD
DfspGetFtDfsName()
{
DWORD dwErr;
DWORD dwType;
DWORD cbName;
HKEY hkey;
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
if (dwErr == ERROR_SUCCESS) {
cbName = sizeof(wszFtDfsName);
dwErr = RegQueryValueEx(
hkey,
FTDFS_VALUE_NAME,
NULL,
&dwType,
(PBYTE) wszFtDfsName,
&cbName);
if (dwErr == ERROR_SUCCESS && dwType != REG_SZ) {
dwErr = ERROR_FILE_NOT_FOUND;
}
RegCloseKey( hkey );
if (dwErr == ERROR_SUCCESS) {
pwszFtDfsName = wszFtDfsName;
} else {
pwszFtDfsName = NULL;
}
}
return dwErr;
}
//+----------------------------------------------------------------------------
//
// Function: GetConfigSwitches
//
// Synopsis: Get configuration switches from the registry
//
// Arguments: None
//
//-----------------------------------------------------------------------------
VOID
GetConfigSwitches()
{
DWORD dwErr;
DWORD dwType;
DWORD cbData;
HKEY hkey;
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, REG_KEY_DFSSVC, &hkey );
if (dwErr == ERROR_SUCCESS) {
cbData = sizeof(DfsDnsConfig);
dwErr = RegQueryValueEx(
hkey,
REG_VALUE_DFSDNSCONFIG,
NULL,
&dwType,
(PBYTE) &DfsDnsConfig,
&cbData);
if (!(dwErr == ERROR_SUCCESS && dwType == REG_DWORD))
DfsDnsConfig = 0;
cbData = sizeof(DfsSvcLdap);
dwErr = RegQueryValueEx(
hkey,
REG_VALUE_LDAP,
NULL,
&dwType,
(PBYTE) &DfsSvcLdap,
&cbData);
if (!(dwErr == ERROR_SUCCESS && dwType == REG_DWORD))
DfsSvcLdap = 0;
RegCloseKey(hkey);
}
}
//+----------------------------------------------------------------------------
//
// Function: GetEventLogSwitches
//
// Synopsis: Gets the event log switch values
//
// Arguments: None
//
//-----------------------------------------------------------------------------
VOID
GetEventLogSwitches()
{
DWORD dwErr;
DWORD dwType;
DWORD cbData;
HKEY hkey = NULL;
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, REG_KEY_EVENTLOG, &hkey );
if (dwErr == ERROR_SUCCESS) {
cbData = sizeof(DfsEventLog);
dwErr = RegQueryValueEx(
hkey,
REG_VALUE_EVENTLOG_GLOBAL,
NULL,
&dwType,
(PBYTE) &DfsEventLog,
&cbData);
if (dwErr == ERROR_SUCCESS && dwType == REG_DWORD)
goto Cleanup;
DfsEventLog = 0;
cbData = sizeof(DfsEventLog);
dwErr = RegQueryValueEx(
hkey,
REG_VALUE_EVENTLOG_DFS,
NULL,
&dwType,
(PBYTE) &DfsEventLog,
&cbData);
if (dwErr == ERROR_SUCCESS && dwType == REG_DWORD)
goto Cleanup;
//
// Could not find either the global nor the dfs event log setting
//
DfsEventLog = 0;
}
#if DBG
if (DfsSvcVerbose)
DbgPrint("Dfssvc:DfsEventLog = 0x%x\n", DfsEventLog);
#endif
Cleanup:
if (hkey != NULL)
RegCloseKey(hkey);
}
#if DBG
//+----------------------------------------------------------------------------
//
// Function: GetDebugSwitches
//
// Synopsis: Gets the debug switch values
//
// Arguments: None
//
//-----------------------------------------------------------------------------
VOID
GetDebugSwitches()
{
DWORD dwErr;
DWORD dwType;
DWORD cbData;
HKEY hkey;
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, REG_KEY_DFSSVC, &hkey );
if (dwErr == ERROR_SUCCESS) {
cbData = sizeof(DfsSvcVerbose);
dwErr = RegQueryValueEx(
hkey,
REG_VALUE_VERBOSE,
NULL,
&dwType,
(PBYTE) &DfsSvcVerbose,
&cbData);
if (!(dwErr == ERROR_SUCCESS && dwType == REG_DWORD)) {
DfsSvcVerbose = 0;
}
cbData = sizeof(IDfsVolInfoLevel);
dwErr = RegQueryValueEx(
hkey,
REG_VALUE_IDFSVOL,
NULL,
&dwType,
(PBYTE) &IDfsVolInfoLevel,
&cbData);
if (!(dwErr == ERROR_SUCCESS && dwType == REG_DWORD)) {
IDfsVolInfoLevel = DEF_INFOLEVEL;
}
RegCloseKey(hkey);
}
}
#endif
//+------------------------------------------------------------------------
//
// Function: LogMessage()
//
// Synopsis: This method takes an error code and a list of strings and
// displays the right message for now. Later on this will have
// to raise an event and do the appropriate stuff actually.
//
// Arguments: [ErrNum] -- Error Number (SCODE). This identifies message to
// pick up.
// [pwcstrs] -- The strings that are to be displayed.
// [count] -- Number of strings in above array.
// [Severity] -- The severity of the error so that we can turn
// off debuggin selectively.
//
// Returns: Nothing.
//
// Notes:
//
// History: 10-Feb-1993 SudK Created.
//
//-------------------------------------------------------------------------
VOID
LogMessageFull(
DWORD Severity,
PWCHAR pwcstrs[],
DWORD count,
DWORD ErrNum)
{
IDfsVolInlineDebOut(( Severity, " [%ws] \n", DfsErrString[ErrNum] ));
for (ULONG _i=0; _i<count; _i++) {
IDfsVolInlineDebOut(( Severity, "Str%d : [%ws] \n", _i, pwcstrs[_i] ));
}
IDfsVolInlineDebOut((Severity, "***%s @ %d *****\n", __FILE__, __LINE__));
}