1044 lines
24 KiB
C
1044 lines
24 KiB
C
//+----------------------------------------------------------------------------
|
||
//
|
||
// 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;
|
||
}
|