Leaked source code of windows server 2003
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.
 
 
 
 
 
 

517 lines
13 KiB

//--------------------------------------------------------------------
// netlogon - implementation
// Copyright (C) Microsoft Corporation, 2001
//
// Created by: Duncan Bryce (duncanb), 06-24-2002
//
// Helper routines for w32time's interaction with the netlogon service.
// Copied from \\index1\sdnt\ds\netapi\svcdlls\logonsrv\client\getdcnam.c
//
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <winsvc.h>
#include <lmcons.h>
#include <lmsname.h>
#include "netlogon.h"
BOOLEAN
NlReadDwordHklmRegValue(
IN LPCSTR SubKey,
IN LPCSTR ValueName,
OUT PDWORD ValueRead
)
/*++
Routine Description:
Reads a DWORD from the specified registry location.
Arguments:
SubKey - Subkey of the value to read.
ValueName - The name of the value to read.
ValueRead - Returns the value read from the registry.
Return Status:
TRUE - We've successfully read the data.
FALSE - We've not been able to read the data successfully.
--*/
{
LONG RegStatus;
HKEY KeyHandle = NULL;
DWORD ValueType;
DWORD Value;
DWORD ValueSize;
//
// Open the key
//
RegStatus = RegOpenKeyExA(
HKEY_LOCAL_MACHINE,
SubKey,
0, //Reserved
KEY_QUERY_VALUE,
&KeyHandle );
if ( RegStatus != ERROR_SUCCESS ) {
if ( RegStatus != ERROR_FILE_NOT_FOUND ) {
// NlPrint(( NL_CRITICAL,
// "NlReadDwordHklmRegValue: Cannot open registy key 'HKLM\\%s' %ld.\n",
// SubKey,
// RegStatus ));
}
return FALSE;
}
//
// Get the value
//
ValueSize = sizeof(Value);
RegStatus = RegQueryValueExA(
KeyHandle,
ValueName,
0,
&ValueType,
(LPBYTE)&Value,
&ValueSize );
RegCloseKey( KeyHandle );
if ( RegStatus != ERROR_SUCCESS ) {
if ( RegStatus != ERROR_FILE_NOT_FOUND ) {
// NlPrint(( NL_CRITICAL,
// "NlReadDwordHklmRegValue: Cannot query value of 'HKLM\\%s\\%s' %ld.\n",
// SubKey,
// ValueName,
// RegStatus ));
}
return FALSE;
}
if ( ValueType != REG_DWORD ) {
// NlPrint(( NL_CRITICAL,
// "NlReadDwordHklmRegValue: value of 'HKLM\\%s\\%s'is not a REG_DWORD %ld.\n",
// SubKey,
// ValueName,
// ValueType ));
return FALSE;
}
if ( ValueSize != sizeof(Value) ) {
// NlPrint(( NL_CRITICAL,
// "NlReadDwordHklmRegValue: value size of 'HKLM\\%s\\%s'is not 4 %ld.\n",
// SubKey,
// ValueName,
// ValueSize ));
return FALSE;
}
//
// We've successfully read the data
//
*ValueRead = Value;
return TRUE;
}
BOOLEAN
NlDoingSetup(
VOID
)
/*++
Routine Description:
Returns TRUE if we're running setup.
Arguments:
NONE.
Return Status:
TRUE - We're currently running setup
FALSE - We're not running setup or aren't sure.
--*/
{
DWORD Value;
if ( !NlReadDwordHklmRegValue( "SYSTEM\\Setup",
"SystemSetupInProgress",
&Value ) ) {
return FALSE;
}
if ( Value != 1 ) {
// NlPrint(( 0, "NlDoingSetup: not doing setup\n" ));
return FALSE;
}
// NlPrint(( 0, "NlDoingSetup: doing setup\n" ));
return TRUE;
}
NTSTATUS
NlWaitForEvent(
LPWSTR EventName,
ULONG Timeout
)
/*++
Routine Description:
Wait up to Timeout seconds for EventName to be triggered.
Arguments:
EventName - Name of event to wait on
Timeout - Timeout for event (in seconds).
Return Status:
STATUS_SUCCESS - Indicates NETLOGON successfully initialized.
STATUS_NETLOGON_NOT_STARTED - Timeout occurred.
--*/
{
NTSTATUS Status;
HANDLE EventHandle;
OBJECT_ATTRIBUTES EventAttributes;
UNICODE_STRING EventNameString;
LARGE_INTEGER LocalTimeout;
//
// Create an event for us to wait on.
//
RtlInitUnicodeString( &EventNameString, EventName);
InitializeObjectAttributes( &EventAttributes, &EventNameString, 0, 0, NULL);
Status = NtCreateEvent(
&EventHandle,
SYNCHRONIZE,
&EventAttributes,
NotificationEvent,
(BOOLEAN) FALSE // The event is initially not signaled
);
if ( !NT_SUCCESS(Status)) {
//
// If the event already exists, the server beat us to creating it.
// Just open it.
//
if( Status == STATUS_OBJECT_NAME_EXISTS ||
Status == STATUS_OBJECT_NAME_COLLISION ) {
Status = NtOpenEvent( &EventHandle,
SYNCHRONIZE,
&EventAttributes );
}
if ( !NT_SUCCESS(Status)) {
// NlPrint((0,"[NETAPI32] OpenEvent failed %lx\n", Status ));
return Status;
}
}
//
// Wait for NETLOGON to initialize. Wait a maximum of Timeout seconds.
//
LocalTimeout.QuadPart = ((LONGLONG)(Timeout)) * (-10000000);
Status = NtWaitForSingleObject( EventHandle, (BOOLEAN)FALSE, &LocalTimeout);
(VOID) NtClose( EventHandle );
if ( !NT_SUCCESS(Status) || Status == STATUS_TIMEOUT ) {
if ( Status == STATUS_TIMEOUT ) {
Status = STATUS_NETLOGON_NOT_STARTED; // Map to an error condition
}
return Status;
}
return STATUS_SUCCESS;
}
NTSTATUS
NlWaitForNetlogon(
ULONG Timeout
)
/*++
Routine Description:
Wait up to Timeout seconds for the netlogon service to start.
Arguments:
Timeout - Timeout for event (in seconds).
Return Status:
STATUS_SUCCESS - Indicates NETLOGON successfully initialized.
STATUS_NETLOGON_NOT_STARTED - Timeout occurred.
--*/
{
NTSTATUS Status;
NET_API_STATUS NetStatus;
SC_HANDLE ScManagerHandle = NULL;
SC_HANDLE ServiceHandle = NULL;
SERVICE_STATUS ServiceStatus;
LPQUERY_SERVICE_CONFIG ServiceConfig;
LPQUERY_SERVICE_CONFIG AllocServiceConfig = NULL;
QUERY_SERVICE_CONFIG DummyServiceConfig;
DWORD ServiceConfigSize;
//
// If the netlogon service is currently running,
// skip the rest of the tests.
//
Status = NlWaitForEvent( L"\\NETLOGON_SERVICE_STARTED", 0 );
if ( NT_SUCCESS(Status) ) {
return Status;
}
//
// If we're in setup,
// don't bother waiting for netlogon to start.
//
if ( NlDoingSetup() ) {
return STATUS_NETLOGON_NOT_STARTED;
}
//
// Open a handle to the Netlogon Service.
//
ScManagerHandle = OpenSCManager(
NULL,
NULL,
SC_MANAGER_CONNECT );
if (ScManagerHandle == NULL) {
// NlPrint((0, "[NETAPI32] NlWaitForNetlogon: OpenSCManager failed: "
// "%lu\n", GetLastError()));
Status = STATUS_NETLOGON_NOT_STARTED;
goto Cleanup;
}
ServiceHandle = OpenService(
ScManagerHandle,
SERVICE_NETLOGON,
SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG );
if ( ServiceHandle == NULL ) {
//NlPrint((0, "[NETAPI32] NlWaitForNetlogon: OpenService failed: "
// "%lu\n", GetLastError()));
Status = STATUS_NETLOGON_NOT_STARTED;
goto Cleanup;
}
//
// If the Netlogon service isn't configured to be automatically started
// by the service controller, don't bother waiting for it to start.
//
// ?? Pass "DummyServiceConfig" and "sizeof(..)" since QueryService config
// won't allow a null pointer, yet.
if ( QueryServiceConfig(
ServiceHandle,
&DummyServiceConfig,
sizeof(DummyServiceConfig),
&ServiceConfigSize )) {
ServiceConfig = &DummyServiceConfig;
} else {
NetStatus = GetLastError();
if ( NetStatus != ERROR_INSUFFICIENT_BUFFER ) {
//NlPrint((0, "[NETAPI32] NlWaitForNetlogon: QueryServiceConfig failed: "
// "%lu\n", NetStatus));
Status = STATUS_NETLOGON_NOT_STARTED;
goto Cleanup;
}
AllocServiceConfig = (LPQUERY_SERVICE_CONFIG)LocalAlloc( 0, ServiceConfigSize );
ServiceConfig = AllocServiceConfig;
if ( AllocServiceConfig == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
if ( !QueryServiceConfig(
ServiceHandle,
ServiceConfig,
ServiceConfigSize,
&ServiceConfigSize )) {
//NlPrint((0, "[NETAPI32] NlWaitForNetlogon: QueryServiceConfig "
// "failed again: %lu\n", GetLastError()));
Status = STATUS_NETLOGON_NOT_STARTED;
goto Cleanup;
}
}
if ( ServiceConfig->dwStartType != SERVICE_AUTO_START ) {
// NlPrint((0, "[NETAPI32] NlWaitForNetlogon: Netlogon start type invalid:"
// "%lu\n", ServiceConfig->dwStartType ));
Status = STATUS_NETLOGON_NOT_STARTED;
goto Cleanup;
}
//
// Loop waiting for the netlogon service to start.
// (Convert Timeout to a number of 10 second iterations)
//
Timeout = (Timeout+9)/10;
for (;;) {
//
// Query the status of the Netlogon service.
//
if (! QueryServiceStatus( ServiceHandle, &ServiceStatus )) {
// NlPrint((0, "[NETAPI32] NlWaitForNetlogon: QueryServiceStatus failed: "
// "%lu\n", GetLastError() ));
Status = STATUS_NETLOGON_NOT_STARTED;
goto Cleanup;
}
//
// Return or continue waiting depending on the state of
// the netlogon service.
//
switch( ServiceStatus.dwCurrentState) {
case SERVICE_RUNNING:
Status = STATUS_SUCCESS;
goto Cleanup;
case SERVICE_STOPPED:
//
// If Netlogon failed to start,
// error out now. The caller has waited long enough to start.
//
if ( ServiceStatus.dwWin32ExitCode != ERROR_SERVICE_NEVER_STARTED ){
#if NETLOGONDBG
// NlPrint((0, "[NETAPI32] NlWaitForNetlogon: "
// "Netlogon service couldn't start: %lu %lx\n",
// ServiceStatus.dwWin32ExitCode,
// ServiceStatus.dwWin32ExitCode ));
if ( ServiceStatus.dwWin32ExitCode == ERROR_SERVICE_SPECIFIC_ERROR ) {
// NlPrint((0, " Service specific error code: %lu %lx\n",
// ServiceStatus.dwServiceSpecificExitCode,
// ServiceStatus.dwServiceSpecificExitCode ));
}
#endif // DBG
Status = STATUS_NETLOGON_NOT_STARTED;
goto Cleanup;
}
//
// If Netlogon has never been started on this boot,
// continue waiting for it to start.
//
break;
//
// If Netlogon is trying to start up now,
// continue waiting for it to start.
//
case SERVICE_START_PENDING:
break;
//
// Any other state is bogus.
//
default:
// NlPrint((0, "[NETAPI32] NlWaitForNetlogon: "
// "Invalid service state: %lu\n",
// ServiceStatus.dwCurrentState ));
Status = STATUS_NETLOGON_NOT_STARTED;
goto Cleanup;
}
//
// Wait ten seconds for the netlogon service to start.
// If it has successfully started, just return now.
//
Status = NlWaitForEvent( L"\\NETLOGON_SERVICE_STARTED", 10 );
if ( Status != STATUS_NETLOGON_NOT_STARTED ) {
goto Cleanup;
}
//
// If we've waited long enough for netlogon to start,
// time out now.
//
if ( (--Timeout) == 0 ) {
Status = STATUS_NETLOGON_NOT_STARTED;
goto Cleanup;
}
}
/* NOT REACHED */
Cleanup:
if ( ScManagerHandle != NULL ) {
(VOID) CloseServiceHandle(ScManagerHandle);
}
if ( ServiceHandle != NULL ) {
(VOID) CloseServiceHandle(ServiceHandle);
}
if ( AllocServiceConfig != NULL ) {
LocalFree( AllocServiceConfig );
}
return Status;
}