mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1043 lines
24 KiB
1043 lines
24 KiB
//+----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 1992, Microsoft Corporation
|
|
//
|
|
// File: dfssvc.c
|
|
//
|
|
// Contents: Code to interact with service manager.
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 12 Nov 92 Milans created.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <dfsfsctl.h>
|
|
#include <windows.h>
|
|
#include <stdlib.h>
|
|
#include <lm.h>
|
|
#include <dsrole.h>
|
|
|
|
#include <dfsstr.h>
|
|
#include <libsup.h>
|
|
#include <dfsmsrv.h>
|
|
|
|
#include <winldap.h>
|
|
|
|
#include "dfsipc.h"
|
|
#include "dominfo.h"
|
|
#include "wmlum.h"
|
|
#include "wmlmacro.h"
|
|
#include "svcwml.h"
|
|
|
|
#include <debug.h>
|
|
DECLARE_DEBUG(DfsSvc)
|
|
DECLARE_INFOLEVEL(DfsSvc)
|
|
|
|
#if DBG == 1
|
|
|
|
#define svc_debug_error(x,y) DfsSvcInlineDebugOut(DEB_ERROR, x, y)
|
|
#define svc_debug_trace(x,y) DfsSvcInlineDebugOut(DEB_TRACE, x, y)
|
|
|
|
#else // DBG == 1
|
|
|
|
#define svc_debug_error(x,y)
|
|
#define svc_debug_trace(x,y)
|
|
|
|
#endif // DBG == 1
|
|
|
|
#define MAX_HINT_PERIODS 1000
|
|
|
|
BOOLEAN fStartAsService;
|
|
const PWSTR wszDfsServiceName = L"DfsService";
|
|
SERVICE_STATUS DfsStatus;
|
|
SERVICE_STATUS_HANDLE hDfsService;
|
|
|
|
VOID DfsSvcMsgProc(
|
|
DWORD dwControl);
|
|
|
|
VOID StartDfsService(
|
|
DWORD dwNumServiceArgs,
|
|
LPWSTR *lpServiceArgs);
|
|
|
|
DWORD
|
|
DfsStartDfssrv(VOID);
|
|
|
|
VOID
|
|
DfsStopDfssrv( VOID);
|
|
|
|
BOOL
|
|
DfsIsThisADfsRoot();
|
|
|
|
DWORD
|
|
DfsInitializationLoop(
|
|
LPVOID lpThreadParams);
|
|
|
|
DWORD DfsManagerProc();
|
|
|
|
DWORD DfsRegDeleteKeyAndChildren(HKEY hkey, LPWSTR s);
|
|
|
|
DWORD DfsCleanLocalVols(void);
|
|
DWORD DfsDeleteChildKeys(HKEY hkey, LPWSTR s);
|
|
|
|
void UpdateStatus(
|
|
SERVICE_STATUS_HANDLE hService,
|
|
SERVICE_STATUS *pSStatus,
|
|
DWORD Status);
|
|
|
|
//
|
|
// Event logging and debugging globals
|
|
//
|
|
extern ULONG DfsSvcVerbose;
|
|
extern ULONG DfsEventLog;
|
|
|
|
typedef void (FAR WINAPI *DLL_ENTRY_PROC)(PWSTR);
|
|
|
|
//
|
|
// Our domain name and machine name
|
|
//
|
|
WCHAR MachineName[MAX_PATH];
|
|
WCHAR DomainName[MAX_PATH];
|
|
WCHAR DomainNameDns[MAX_PATH];
|
|
WCHAR LastMachineName[MAX_PATH];
|
|
WCHAR LastDomainName[MAX_PATH];
|
|
WCHAR SiteName[MAX_PATH];
|
|
CRITICAL_SECTION DomListCritSection;
|
|
|
|
//
|
|
// Our role in life (see dsrole.h)
|
|
//
|
|
DSROLE_MACHINE_ROLE DfsMachineRole;
|
|
|
|
//
|
|
// Type of dfs (FtDfs==DFS_MANAGER_FTDFS/Machine-based==DFS_MANAGER_SERVER)
|
|
//
|
|
ULONG DfsServerType = 0;
|
|
|
|
//
|
|
// Long-lived ldap handle to the ds on this machine, if it is a DC
|
|
//
|
|
PLDAP pLdap = NULL;
|
|
|
|
GUID DfsRtlTraceGuid = { // 79d1da1f-7268-441b-b835-7c7bed5ab39e
|
|
0x79d1da1f, 0x7268, 0x441b,
|
|
{0xb8, 0x35, 0x7c, 0x7b, 0xed, 0x5a, 0xb3, 0x9e}};
|
|
|
|
|
|
extern void DfsInitWml();
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: WinMain
|
|
//
|
|
// Synopsis: This guy will set up link to service manager and install
|
|
// ServiceMain as the service's entry point. Hopefully, the service
|
|
// control dispatcher will call ServiceMain soon thereafter.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int PASCAL WinMain(HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPSTR lpszCmdLine,
|
|
int nCmdShow)
|
|
{
|
|
SERVICE_TABLE_ENTRYW aServiceEntry[2];
|
|
DWORD status;
|
|
|
|
|
|
if (_stricmp( lpszCmdLine, "-noservice" ) == 0) {
|
|
|
|
fStartAsService = FALSE;
|
|
|
|
StartDfsService( 0, NULL );
|
|
|
|
//
|
|
// Since we were not started as a service, we wait for ever...
|
|
//
|
|
|
|
Sleep( INFINITE );
|
|
|
|
} else {
|
|
|
|
fStartAsService = TRUE;
|
|
|
|
aServiceEntry[0].lpServiceName = wszDfsServiceName;
|
|
aServiceEntry[0].lpServiceProc = StartDfsService;
|
|
aServiceEntry[1].lpServiceName = NULL;
|
|
aServiceEntry[1].lpServiceProc = NULL;
|
|
|
|
svc_debug_trace("Starting Dfs Services...\n", 0);
|
|
|
|
if (!StartServiceCtrlDispatcherW(aServiceEntry)) {
|
|
svc_debug_error("Error %d starting as service!\n", GetLastError());
|
|
return(GetLastError());
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// If the StartServiceCtrlDispatcher call succeeded, we will never get to
|
|
// this point until someone stops this service.
|
|
//
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: StartDfsService
|
|
//
|
|
// Synopsis: Call back for DfsService service. This is called *once* by the
|
|
// Service controller when the DfsService service is to be inited
|
|
// This function is responsible for registering a message
|
|
// handler function for the DfsService service.
|
|
//
|
|
// Arguments: Unused
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
StartDfsService(DWORD dwNumServiceArgs, LPWSTR *lpServiceArgs)
|
|
{
|
|
HANDLE hInit;
|
|
DWORD dwErr;
|
|
DWORD idThread;
|
|
HKEY hkey;
|
|
PSECURITY_ATTRIBUTES pSecAttribs = NULL;
|
|
PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pPrimaryDomainInfo;
|
|
ULONG CheckPoint = 0;
|
|
|
|
#if (DBG == 1) || (_CT_TEST_HOOK == 1)
|
|
SECURITY_DESCRIPTOR SD;
|
|
SECURITY_ATTRIBUTES SA;
|
|
BOOL fRC = InitializeSecurityDescriptor(
|
|
&SD,
|
|
SECURITY_DESCRIPTOR_REVISION);
|
|
|
|
if( fRC == TRUE ) {
|
|
|
|
fRC = SetSecurityDescriptorDacl(
|
|
&SD,
|
|
TRUE,
|
|
NULL,
|
|
FALSE);
|
|
|
|
}
|
|
|
|
SA.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
SA.lpSecurityDescriptor = &SD;
|
|
SA.bInheritHandle = FALSE;
|
|
pSecAttribs = &SA;
|
|
|
|
#endif
|
|
|
|
svc_debug_trace("StartDfsService: fStartAsService = %d\n", fStartAsService);
|
|
|
|
if (fStartAsService) {
|
|
|
|
hDfsService = RegisterServiceCtrlHandlerW(
|
|
wszDfsServiceName,
|
|
DfsSvcMsgProc);
|
|
if (!hDfsService) {
|
|
svc_debug_error("Error %d installing Dfs msg handler\n", GetLastError());
|
|
return;
|
|
}
|
|
|
|
DfsStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
|
DfsStatus.dwCurrentState = SERVICE_STOPPED;
|
|
DfsStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
|
DfsStatus.dwWin32ExitCode = 0;
|
|
DfsStatus.dwServiceSpecificExitCode = 0;
|
|
DfsStatus.dwCheckPoint = CheckPoint++;
|
|
DfsStatus.dwWaitHint = 1000 * 30;
|
|
|
|
svc_debug_trace("Updating Status to Start Pending...\n", 0);
|
|
UpdateStatus(hDfsService, &DfsStatus, SERVICE_START_PENDING);
|
|
|
|
}
|
|
|
|
//
|
|
// Remove any old exit pt info from the registry
|
|
//
|
|
|
|
DfsCleanLocalVols();
|
|
|
|
InitializeCriticalSection(&DomListCritSection);
|
|
|
|
//
|
|
// Get our machine name and type/role.
|
|
//
|
|
|
|
|
|
dwErr = DsRoleGetPrimaryDomainInformation(
|
|
NULL,
|
|
DsRolePrimaryDomainInfoBasic,
|
|
(PBYTE *)&pPrimaryDomainInfo);
|
|
|
|
if (dwErr == ERROR_SUCCESS) {
|
|
|
|
DfsMachineRole = pPrimaryDomainInfo->MachineRole;
|
|
|
|
DomainName[0] = LastDomainName[0] = L'\0';
|
|
|
|
DomainNameDns[0] = L'\0';
|
|
|
|
if (pPrimaryDomainInfo->DomainNameFlat != NULL) {
|
|
|
|
if (wcslen(pPrimaryDomainInfo->DomainNameFlat) < MAX_PATH) {
|
|
|
|
wcscpy(DomainName,pPrimaryDomainInfo->DomainNameFlat);
|
|
wcscpy(LastDomainName, DomainName);
|
|
|
|
} else {
|
|
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pPrimaryDomainInfo->DomainNameDns != NULL) {
|
|
|
|
if (wcslen(pPrimaryDomainInfo->DomainNameDns) < MAX_PATH) {
|
|
|
|
wcscpy(DomainNameDns,pPrimaryDomainInfo->DomainNameDns);
|
|
|
|
} else {
|
|
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DsRoleFreeMemory(pPrimaryDomainInfo);
|
|
|
|
}
|
|
|
|
if (dwErr != ERROR_SUCCESS) {
|
|
svc_debug_error("StartDfsService:DsRoleGetPrimaryDomainInformation %08lx!\n", dwErr);
|
|
DfsStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
|
|
DfsStatus.dwServiceSpecificExitCode = dwErr;
|
|
DfsStatus.dwCheckPoint = 0;
|
|
UpdateStatus(hDfsService, &DfsStatus, SERVICE_STOPPED);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Create a thread to finish initialization
|
|
//
|
|
|
|
hInit = CreateThread(
|
|
NULL, // Security attributes
|
|
0, // Use default stack size
|
|
DfsInitializationLoop, // Thread entry procedure
|
|
0, // Thread context parameter
|
|
0, // Start immediately
|
|
&idThread); // Thread ID
|
|
|
|
if (hInit == NULL) {
|
|
svc_debug_error(
|
|
"Unable to create Driver Init thread %08lx\n", GetLastError());
|
|
DfsStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
|
|
DfsStatus.dwServiceSpecificExitCode = GetLastError();
|
|
DfsStatus.dwCheckPoint = 0;
|
|
UpdateStatus(hDfsService, &DfsStatus, SERVICE_STOPPED);
|
|
return;
|
|
}
|
|
else {
|
|
// 428812: no need to keep the handle around. prevent thread leak.
|
|
CloseHandle( hInit );
|
|
}
|
|
|
|
DfsStatus.dwCheckPoint = CheckPoint++;
|
|
UpdateStatus(hDfsService, &DfsStatus, SERVICE_RUNNING);
|
|
return;
|
|
|
|
}
|
|
|
|
DWORD
|
|
DfsInitializationLoop(
|
|
LPVOID lpThreadParams)
|
|
{
|
|
HANDLE hLPC;
|
|
DWORD idLpcThread;
|
|
HANDLE hDfs;
|
|
ULONG Retry;
|
|
DWORD dwErr;
|
|
NTSTATUS Status;
|
|
|
|
Retry = 0;
|
|
|
|
|
|
DfsInitWml();
|
|
do {
|
|
|
|
dwErr = DfsManagerProc();
|
|
|
|
} while (dwErr != ERROR_SUCCESS && ++Retry < 10);
|
|
|
|
if (dwErr != ERROR_SUCCESS) {
|
|
svc_debug_error("Dfs Manager failed %08lx!\n", dwErr);
|
|
}
|
|
|
|
switch (DfsMachineRole) {
|
|
|
|
case DsRole_RoleBackupDomainController:
|
|
case DsRole_RolePrimaryDomainController:
|
|
|
|
|
|
//
|
|
// Init the special name table
|
|
//
|
|
|
|
Retry = 0;
|
|
DfsInitDomainList();
|
|
|
|
do {
|
|
|
|
Status = DfsInitOurDomainDCs();
|
|
|
|
if (Status != ERROR_SUCCESS) {
|
|
|
|
Sleep(10*1000);
|
|
|
|
}
|
|
|
|
} while (Status != ERROR_SUCCESS && ++Retry < 10);
|
|
|
|
DfsInitRemainingDomainDCs();
|
|
|
|
pLdap = ldap_init(L"LocalHost", LDAP_PORT);
|
|
|
|
if (pLdap != NULL) {
|
|
|
|
dwErr = ldap_set_option(pLdap, LDAP_OPT_AREC_EXCLUSIVE, LDAP_OPT_ON);
|
|
|
|
if (dwErr != LDAP_SUCCESS) {
|
|
pLdap = NULL;
|
|
} else {
|
|
|
|
dwErr = ldap_bind_s(pLdap, NULL, NULL, LDAP_AUTH_SSPI);
|
|
|
|
if (dwErr != ERROR_SUCCESS) {
|
|
|
|
svc_debug_error("Could not bind to LocalHost\n", 0);
|
|
pLdap = NULL;
|
|
}
|
|
}
|
|
} else {
|
|
|
|
svc_debug_error("Could not open LocalHost\n", 0);
|
|
|
|
}
|
|
|
|
/* Fall THRU */
|
|
|
|
case DsRole_RoleMemberServer:
|
|
|
|
//
|
|
// Start the dfs lpc server
|
|
//
|
|
|
|
hLPC = CreateThread(
|
|
NULL, // Security attributes
|
|
0, // Use default stack size
|
|
(LPTHREAD_START_ROUTINE)DfsStartDfssrv, // Thread entry procedure
|
|
0, // Thread context parameter
|
|
0, // Start immediately
|
|
&idLpcThread); // Thread ID
|
|
|
|
if (hLPC == NULL) {
|
|
svc_debug_error(
|
|
"Unable to create Driver LPC thread %08lx\n", GetLastError());
|
|
}
|
|
else {
|
|
CloseHandle(hLPC);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
Status = DfsOpen( &hDfs, NULL );
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
switch (DfsMachineRole) {
|
|
|
|
case DsRole_RoleBackupDomainController:
|
|
case DsRole_RolePrimaryDomainController:
|
|
|
|
Status = DfsFsctl(
|
|
hDfs,
|
|
FSCTL_DFS_ISDC,
|
|
NULL,
|
|
0L,
|
|
NULL,
|
|
0L);
|
|
|
|
}
|
|
|
|
NtClose( hDfs );
|
|
|
|
} else {
|
|
|
|
svc_debug_error("Unable to open dfs driver %08lx\n", Status);
|
|
svc_debug_error("UNC names will not work!\n", 0);
|
|
|
|
}
|
|
|
|
switch (DfsMachineRole) {
|
|
|
|
case DsRole_RoleBackupDomainController:
|
|
case DsRole_RolePrimaryDomainController:
|
|
|
|
do {
|
|
|
|
Status = DfsInitRemainingDomainDCs();
|
|
|
|
if (Status != ERROR_SUCCESS) {
|
|
|
|
Sleep(1000 * 60 * 10); // 10 min
|
|
|
|
}
|
|
|
|
} while (Status != ERROR_SUCCESS && ++Retry < 100);
|
|
|
|
|
|
do {
|
|
|
|
Sleep(1000 * 60 * 15); // 15 min
|
|
DfsInitDomainList();
|
|
DfsInitOurDomainDCs();
|
|
DfsInitRemainingDomainDCs();
|
|
|
|
} while (TRUE);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsSvcMsgProc
|
|
//
|
|
// Synopsis: Service-Message handler for DFSInit.
|
|
//
|
|
// Arguments: [dwControl] - the message
|
|
//
|
|
// Returns: nothing
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
DfsSvcMsgProc(DWORD dwControl)
|
|
{
|
|
NTSTATUS Status;
|
|
HANDLE hDfs;
|
|
|
|
switch(dwControl) {
|
|
|
|
case SERVICE_CONTROL_STOP:
|
|
|
|
#if DBG
|
|
if (DfsSvcVerbose)
|
|
DbgPrint("DfsSvcMsgProc(SERVICE_CONTROL_STOP)\n");
|
|
#endif
|
|
//
|
|
// Stop the driver
|
|
//
|
|
|
|
Status = DfsOpen( &hDfs, NULL );
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
Status = DfsFsctl(
|
|
hDfs,
|
|
FSCTL_DFS_STOP_DFS,
|
|
NULL,
|
|
0L,
|
|
NULL,
|
|
0L);
|
|
|
|
svc_debug_trace("Fsctl STOP_DFS returned %08lx\n", Status);
|
|
|
|
Status = DfsFsctl(
|
|
hDfs,
|
|
FSCTL_DFS_RESET_PKT,
|
|
NULL,
|
|
0L,
|
|
NULL,
|
|
0L);
|
|
|
|
svc_debug_trace("Fsctl FSCTL_DFS_RESET_PKT returned %08lx\n", Status);
|
|
|
|
NtClose( hDfs );
|
|
|
|
}
|
|
|
|
#if DBG
|
|
if (DfsSvcVerbose)
|
|
DbgPrint("DfsSvcMsgProc: calling DfsStopDfssvc\n");
|
|
#endif
|
|
|
|
DfsStopDfssrv();
|
|
|
|
#if DBG
|
|
if (DfsSvcVerbose)
|
|
DbgPrint("DfsSvcMsgProc: DfsStopDfssvc returned\n");
|
|
#endif
|
|
|
|
UpdateStatus(hDfsService, &DfsStatus, SERVICE_STOPPED);
|
|
break;
|
|
|
|
case SERVICE_INTERROGATE:
|
|
|
|
#if DBG
|
|
if (DfsSvcVerbose)
|
|
DbgPrint("DfsSvcMsgProc(SERVICE_INTERROGATE)\n");
|
|
#endif
|
|
//
|
|
// We don't seem to be called with SERVICE_INTERROGATE ever!
|
|
//
|
|
if (DfsStatus.dwCurrentState == SERVICE_START_PENDING &&
|
|
DfsStatus.dwCheckPoint < MAX_HINT_PERIODS) {
|
|
|
|
DfsStatus.dwCheckPoint++;
|
|
svc_debug_trace("DFSInit Checkpoint == %d\n", DfsStatus.dwCheckPoint);
|
|
|
|
UpdateStatus(hDfsService, &DfsStatus, SERVICE_START_PENDING);
|
|
|
|
} else {
|
|
|
|
DfsStatus.dwCheckPoint = 0;
|
|
UpdateStatus(hDfsService, &DfsStatus, DfsStatus.dwCurrentState);
|
|
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: UpdateStatus
|
|
//
|
|
// Synopsis: Pushes a ServiceStatus to the service manager.
|
|
//
|
|
// Arguments: [hService] - handle returned from RegisterServiceCtrlHandler
|
|
// [pSStatus] - pointer to service-status block
|
|
// [Status] - The status to set.
|
|
//
|
|
// Returns: Nothing.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static void
|
|
UpdateStatus(SERVICE_STATUS_HANDLE hService, SERVICE_STATUS *pSStatus, DWORD Status)
|
|
{
|
|
if (fStartAsService) {
|
|
|
|
pSStatus->dwCurrentState = Status;
|
|
|
|
if (Status == SERVICE_START_PENDING) {
|
|
pSStatus->dwCheckPoint++;
|
|
pSStatus->dwWaitHint = 1000;
|
|
} else {
|
|
pSStatus->dwCheckPoint = 0;
|
|
pSStatus->dwWaitHint = 0;
|
|
}
|
|
|
|
SetServiceStatus(hService, pSStatus);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsManagerIsDomainDfsEnabled
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
DfsManagerIsDomainDfsEnabled()
|
|
{
|
|
DWORD dwErr;
|
|
HKEY hkey;
|
|
|
|
dwErr = RegOpenKey(HKEY_LOCAL_MACHINE, REG_KEY_ENABLE_DOMAIN_DFS, &hkey);
|
|
|
|
if (dwErr == ERROR_SUCCESS) {
|
|
|
|
RegCloseKey( hkey );
|
|
|
|
return( TRUE );
|
|
|
|
} else {
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsIsThisADfsRoot
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
DfsIsThisADfsRoot()
|
|
{
|
|
DWORD dwErr;
|
|
HKEY hkey;
|
|
|
|
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
|
|
|
|
if (dwErr == ERROR_SUCCESS) {
|
|
|
|
RegCloseKey( hkey );
|
|
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
return( FALSE );
|
|
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsManagerProc
|
|
//
|
|
// Synopsis: The Dfs Manager side implementation of Dfs Service.
|
|
//
|
|
// Arguments: None
|
|
//
|
|
// Returns: TRUE if everything went ok, FALSE otherwise
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
DWORD
|
|
DfsManagerProc()
|
|
{
|
|
DWORD dwErr;
|
|
PWKSTA_INFO_100 wkstaInfo = NULL;
|
|
HKEY hkey;
|
|
WCHAR wszFTDfsName[ MAX_PATH ];
|
|
DWORD cbName, dwType;
|
|
BOOLEAN fIsFTDfs = FALSE;
|
|
|
|
//
|
|
// Get our Machine name
|
|
//
|
|
|
|
dwErr = NetWkstaGetInfo( NULL, 100, (LPBYTE *) &wkstaInfo );
|
|
|
|
if (dwErr == ERROR_SUCCESS) {
|
|
|
|
if (wcslen(wkstaInfo->wki100_computername) < MAX_PATH) {
|
|
|
|
wcscpy(MachineName,wkstaInfo->wki100_computername);
|
|
wcscpy(LastMachineName, MachineName);
|
|
|
|
} else {
|
|
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
}
|
|
|
|
NetApiBufferFree( wkstaInfo );
|
|
|
|
}
|
|
|
|
if (dwErr != ERROR_SUCCESS) {
|
|
svc_debug_error("DfsManagerProc:NetWkstaGetInfo %08lx!\n", dwErr);
|
|
}
|
|
|
|
//
|
|
// Check VOLUMES_DIR, if it exists, get machine and domain name, and determine
|
|
// if this is an FtDfs participant
|
|
//
|
|
|
|
if (dwErr == ERROR_SUCCESS) {
|
|
|
|
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, VOLUMES_DIR, &hkey );
|
|
|
|
if (dwErr == ERROR_SUCCESS) {
|
|
|
|
cbName = sizeof(LastMachineName);
|
|
|
|
dwErr = RegQueryValueEx(
|
|
hkey,
|
|
MACHINE_VALUE_NAME,
|
|
NULL,
|
|
&dwType,
|
|
(PBYTE) LastMachineName,
|
|
&cbName);
|
|
|
|
if (dwErr != ERROR_SUCCESS) {
|
|
|
|
dwErr = RegSetValueEx(
|
|
hkey,
|
|
MACHINE_VALUE_NAME,
|
|
0,
|
|
REG_SZ,
|
|
(PCHAR)MachineName,
|
|
wcslen(MachineName) * sizeof(WCHAR));
|
|
|
|
} else if (dwType != REG_SZ) {
|
|
|
|
LastMachineName[0] = L'\0';
|
|
|
|
}
|
|
|
|
cbName = sizeof(LastDomainName);
|
|
|
|
dwErr = RegQueryValueEx(
|
|
hkey,
|
|
DOMAIN_VALUE_NAME,
|
|
NULL,
|
|
&dwType,
|
|
(PBYTE) LastDomainName,
|
|
&cbName);
|
|
|
|
if (dwErr != ERROR_SUCCESS) {
|
|
|
|
dwErr = RegSetValueEx(
|
|
hkey,
|
|
DOMAIN_VALUE_NAME,
|
|
0,
|
|
REG_SZ,
|
|
(PCHAR)DomainName,
|
|
wcslen(DomainName) * sizeof(WCHAR));
|
|
|
|
} else if (dwType != REG_SZ) {
|
|
|
|
LastDomainName[0] = L'\0';
|
|
|
|
}
|
|
|
|
//
|
|
// See if this is a Fault-Tolerant Dfs vs Server-Based Dfs
|
|
//
|
|
|
|
cbName = sizeof(wszFTDfsName);
|
|
|
|
dwErr = RegQueryValueEx(
|
|
hkey,
|
|
FTDFS_VALUE_NAME,
|
|
NULL,
|
|
&dwType,
|
|
(PBYTE) wszFTDfsName,
|
|
&cbName);
|
|
|
|
if ((dwErr == ERROR_SUCCESS) && (dwType == REG_SZ)) {
|
|
|
|
fIsFTDfs = TRUE;
|
|
|
|
}
|
|
|
|
RegCloseKey( hkey );
|
|
|
|
}
|
|
|
|
dwErr = ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Now we check if the machine role is appropriate
|
|
//
|
|
|
|
if (dwErr == ERROR_SUCCESS) {
|
|
|
|
switch(DfsMachineRole) {
|
|
|
|
//
|
|
// Somehow we were started on a workstation
|
|
//
|
|
case DsRole_RoleStandaloneWorkstation:
|
|
case DsRole_RoleMemberWorkstation:
|
|
dwErr = ERROR_NOT_SUPPORTED;
|
|
break;
|
|
|
|
//
|
|
// We can run, but not in FtDFS mode,
|
|
//
|
|
// If the domain name has changed, clean up the registry.
|
|
//
|
|
case DsRole_RoleStandaloneServer:
|
|
if (fIsFTDfs == TRUE || _wcsicmp(DomainName, LastDomainName) != 0) {
|
|
fIsFTDfs = FALSE;
|
|
}
|
|
break;
|
|
|
|
//
|
|
// Fully supported modes
|
|
//
|
|
case DsRole_RoleMemberServer:
|
|
case DsRole_RoleBackupDomainController:
|
|
case DsRole_RolePrimaryDomainController:
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if (dwErr == ERROR_SUCCESS) {
|
|
|
|
if (fIsFTDfs) {
|
|
|
|
dwErr = DfsManager(
|
|
wszFTDfsName,
|
|
DFS_MANAGER_FTDFS );
|
|
|
|
} else {
|
|
|
|
dwErr = DfsManager(
|
|
MachineName,
|
|
DFS_MANAGER_SERVER );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return( dwErr );
|
|
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsCleanLocalVols
|
|
//
|
|
// Synopsis: Cleans out the LocalVolumes part of the registry, if there are
|
|
// dfs-link keys left over from older versions.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
DWORD
|
|
DfsCleanLocalVols(void)
|
|
{
|
|
HKEY hLvolKey = NULL;
|
|
HKEY hRootKey = NULL;
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
PWCHAR wCp;
|
|
|
|
wCp = malloc(4096);
|
|
if (wCp == NULL) {
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
dwErr = RegOpenKey( HKEY_LOCAL_MACHINE, REG_KEY_LOCAL_VOLUMES, &hLvolKey);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
goto Cleanup;
|
|
|
|
//
|
|
// Find the key representing the root
|
|
//
|
|
dwErr = RegEnumKey(hLvolKey, 0, wCp, 100);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
goto Cleanup;
|
|
|
|
dwErr = RegOpenKey(hLvolKey, wCp, &hRootKey);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
goto Cleanup;
|
|
|
|
while (dwErr == ERROR_SUCCESS && RegEnumKey(hRootKey, 0, wCp, 100) == ERROR_SUCCESS)
|
|
dwErr = DfsDeleteChildKeys(hRootKey, wCp);
|
|
|
|
Cleanup:
|
|
|
|
if (hLvolKey != NULL)
|
|
RegCloseKey(hLvolKey);
|
|
|
|
if (hRootKey != NULL)
|
|
RegCloseKey(hRootKey);
|
|
|
|
if (wCp != NULL)
|
|
free(wCp);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DfsRegDeleteChildKeys
|
|
//
|
|
// Synopsis: Helper for DfsRegDeleteKeyAndChildren
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: ERROR_SUCCESS or failure code
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
DWORD
|
|
DfsDeleteChildKeys(HKEY hKey, LPWSTR s)
|
|
{
|
|
WCHAR *wCp;
|
|
HKEY nKey = NULL;
|
|
DWORD dwErr;
|
|
DWORD i = 0;
|
|
|
|
dwErr = RegOpenKey(hKey, s, &nKey);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
return dwErr;
|
|
|
|
for (wCp = s; *wCp; wCp++)
|
|
;
|
|
while (dwErr == ERROR_SUCCESS && RegEnumKey(nKey, 0, wCp, 100) == ERROR_SUCCESS)
|
|
dwErr = DfsDeleteChildKeys(nKey, wCp);
|
|
|
|
*wCp = L'\0';
|
|
if (nKey != NULL)
|
|
RegCloseKey(nKey);
|
|
|
|
dwErr = RegDeleteKey(hKey, s);
|
|
|
|
return dwErr;
|
|
}
|