📄 nlmain.c
字号:
return STATUS_NETLOGON_NOT_STARTED;
}
//
// Open a handle to the Netlogon Service.
//
ScManagerHandle = OpenSCManager(
NULL,
NULL,
SC_MANAGER_CONNECT );
if (ScManagerHandle == NULL) {
KdPrint(( "[MSV1_0] 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 ) {
KdPrint(( "[MSV1_0] 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 ) {
KdPrint(( "[MSV1_0] NlWaitForNetlogon: QueryServiceConfig failed: "
"%lu\n", NetStatus));
Status = STATUS_NETLOGON_NOT_STARTED;
goto Cleanup;
}
AllocServiceConfig = RtlAllocateHeap( MspHeap, 0, ServiceConfigSize );
ServiceConfig = AllocServiceConfig;
if ( AllocServiceConfig == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
if ( !QueryServiceConfig(
ServiceHandle,
ServiceConfig,
ServiceConfigSize,
&ServiceConfigSize )) {
KdPrint(( "[MSV1_0] NlWaitForNetlogon: QueryServiceConfig "
"failed again: %lu\n", GetLastError()));
Status = STATUS_NETLOGON_NOT_STARTED;
goto Cleanup;
}
}
if ( ServiceConfig->dwStartType != SERVICE_AUTO_START ) {
KdPrint(( "[MSV1_0] 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 )) {
KdPrint(( "[MSV1_0] 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 DBG
KdPrint(( "[MSV1_0] NlWaitForNetlogon: "
"Netlogon service couldn't start: %lu %lx\n",
ServiceStatus.dwWin32ExitCode,
ServiceStatus.dwWin32ExitCode ));
if ( ServiceStatus.dwWin32ExitCode == ERROR_SERVICE_SPECIFIC_ERROR ) {
KdPrint(( " 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:
KdPrint(( "[MSV1_0] 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 ) {
RtlFreeHeap( MspHeap, 0, AllocServiceConfig );
}
return Status;
}
NTSTATUS
NlSamInitialize(
ULONG Timeout
)
/*++
Routine Description:
Initialize the MSV1_0 Authentication Package's communication to the SAM
database. This initialization will take place once immediately prior
to the first actual use of the SAM database.
Arguments:
Timeout - Timeout for event (in seconds).
Return Status:
STATUS_SUCCESS - Indicates NETLOGON successfully initialized.
--*/
{
NTSTATUS Status;
//
// locals that are staging area for globals.
//
LSA_HANDLE PolicyHandle = NULL;
UNICODE_STRING PrimaryDomainName;
PSID SamDomainId = NULL;
UNICODE_STRING SamDomainName;
SAMPR_HANDLE SamDomainHandle = NULL;
BOOLEAN UasCompatibilityRequired;
OBJECT_ATTRIBUTES PolicyObjectAttributes;
PLSAPR_POLICY_INFORMATION PolicyPrimaryDomainInfo = NULL;
PLSAPR_POLICY_INFORMATION PolicyAccountDomainInfo = NULL;
SAMPR_HANDLE SamHandle = NULL;
#ifdef SAM
PSAMPR_DOMAIN_INFO_BUFFER DomainInfo = NULL;
#endif // SAM
PrimaryDomainName.Buffer = NULL;
SamDomainName.Buffer = NULL;
//
// Wait for SAM to finish initialization.
//
Status = NlWaitForEvent( L"\\SAM_SERVICE_STARTED", Timeout );
if ( !NT_SUCCESS(Status) ) {
goto Cleanup;
}
//
// Determine the DomainName and DomainId of the Account Database
//
InitializeObjectAttributes( &PolicyObjectAttributes,
NULL, // Name
0, // Attributes
NULL, // Root
NULL ); // Security Descriptor
Status = I_LsaIOpenPolicyTrusted(&PolicyHandle);
if ( !NT_SUCCESS(Status) ) {
goto Cleanup;
}
ASSERT(PolicyHandle);
Status = I_LsarQueryInformationPolicy( PolicyHandle,
PolicyAccountDomainInformation,
&PolicyAccountDomainInfo );
if ( !NT_SUCCESS(Status) ) {
goto Cleanup;
}
if ( PolicyAccountDomainInfo->PolicyAccountDomainInfo.DomainSid == NULL ||
PolicyAccountDomainInfo->PolicyAccountDomainInfo.DomainName.Length == 0 ) {
KdPrint(( "MsV1_0: Account domain info from LSA invalid.\n"));
Status = STATUS_NO_SUCH_DOMAIN;
goto Cleanup;
}
Status = I_LsarQueryInformationPolicy(
PolicyHandle,
PolicyPrimaryDomainInformation,
&PolicyPrimaryDomainInfo );
if ( !NT_SUCCESS(Status) ) {
goto Cleanup;
}
if ( PolicyPrimaryDomainInfo->PolicyPrimaryDomainInfo.Name.Length == 0 )
{
KdPrint(( "MsV1_0: Primary domain info from LSA invalid.\n"));
Status = STATUS_NO_SUCH_DOMAIN;
goto Cleanup;
}
//
// save PrimaryDomainName
//
PrimaryDomainName.Length = PolicyPrimaryDomainInfo->PolicyPrimaryDomainInfo.Name.Length;
PrimaryDomainName.MaximumLength = PrimaryDomainName.Length;
PrimaryDomainName.Buffer =
(PWSTR)RtlAllocateHeap( MspHeap, 0, PrimaryDomainName.MaximumLength );
if ( PrimaryDomainName.Buffer == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
RtlCopyMemory( PrimaryDomainName.Buffer,
PolicyPrimaryDomainInfo->PolicyPrimaryDomainInfo.Name.Buffer,
PrimaryDomainName.Length );
//
// Save the domain id of this domain
//
SamDomainId = RtlAllocateHeap(
MspHeap, 0,
RtlLengthSid( PolicyAccountDomainInfo->PolicyAccountDomainInfo.DomainSid ));
if ( SamDomainId == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
RtlCopyMemory( SamDomainId,
PolicyAccountDomainInfo->PolicyAccountDomainInfo.DomainSid,
RtlLengthSid( PolicyAccountDomainInfo->PolicyAccountDomainInfo.DomainSid ));
//
// Save the name of the account database on this machine.
//
// On a workstation, the account database is refered to by the machine
// name and not the database name.
// The above being true, the machine name is set to MACHINENAME during
// setup and for the duration when the machine has a real machine name
// until the end of setup, NlpSamDomainName will still have MACHINENAME.
// This is not what the caller expects to authenticate against, so we
// force a look from the Lsa all the time.
// We assume that NlpSamDomainName will get the right info from the Lsa
SamDomainName.Length = PolicyAccountDomainInfo->PolicyAccountDomainInfo.DomainName.Length;
SamDomainName.MaximumLength = (USHORT)
(SamDomainName.Length + sizeof(WCHAR));
SamDomainName.Buffer =
RtlAllocateHeap( MspHeap, 0, SamDomainName.MaximumLength );
if ( SamDomainName.Buffer == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
RtlCopyMemory( SamDomainName.Buffer,
PolicyAccountDomainInfo->PolicyAccountDomainInfo.DomainName.Buffer,
SamDomainName.MaximumLength );
//
// Open our connection with SAM
//
Status = I_SamIConnect( NULL, // No server name
&SamHandle,
SAM_SERVER_CONNECT,
(BOOLEAN) TRUE ); // Indicate we are privileged
if ( !NT_SUCCESS(Status) ) {
SamHandle = NULL;
KdPrint(( "MsV1_0: Cannot SamIConnect %lX\n", Status));
goto Cleanup;
}
//
// Open the domain.
//
Status = I_SamrOpenDomain( SamHandle,
DOMAIN_ALL_ACCESS,
SamDomainId,
&SamDomainHandle );
if ( !NT_SUCCESS(Status) ) {
SamDomainHandle = NULL;
KdPrint(( "MsV1_0: Cannot SamrOpenDomain %lX\n", Status));
goto Cleanup;
}
#ifdef SAM
#error
//
// Ensure the role in SAM is compatible with Netlogon's role
// ?? Use DomainUasInformation once it is defined
//
Status = I_SamrQueryInformationDomain( SamDomainHandle,
DomainGeneralInformation,
&DomainInfo );
if ( !NT_SUCCESS(Status) ) {
DomainInfo = NULL;
KdPrint(( "MsV1_0: Cannot SamrQueryInformationDomain %lX\n", Status));
goto Cleanup;
}
// ?? Doesn't define this properly
UasCompatibilityRequired = DomainInfo->General.UasCompatibilityRequired;
I_SamIFree_SAMPR_DOMAIN_INFO_BUFFER( DomainInfo, DomainGeneralInformation );
#endif // SAM
Status = STATUS_SUCCESS;
EnterCriticalSection(&NtLmGlobalCritSect);
if( !NlpSamInitialized ) {
NlpPolicyHandle = PolicyHandle;
NlpPrimaryDomainName = PrimaryDomainName;
NlpSamDomainId = SamDomainId;
NlpSamDomainName = SamDomainName;
NlpSamDomainHandle = SamDomainHandle;
//
// mark locals invalid so they don't get freed.
//
PolicyHandle = NULL;
PrimaryDomainName.Buffer = NULL;
SamDomainId = NULL;
SamDomainName.Buffer = NULL;
SamDomainHandle = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -