//+---------------------------------------------------------------------------- // // Copyright (C) 1995, Microsoft Corporation // // File: dfsminit.cxx // // Contents: Initialization code for Dfs Manager service. // // Classes: // // Functions: DfsManager -- // DfsInitGlobals -- // InitializeDfsManager -- // InitializeVolumeObject -- // DfsHandleKnowledgeInconsistency -- // //----------------------------------------------------------------------------- //#include //#include //#include //#include //#include #include #pragma hdrstop #include // For EA_NAME_OPENIFJP #include // For public function #include #include #include #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