summaryrefslogtreecommitdiffstats
path: root/private/lsa/server/services.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/lsa/server/services.c')
-rw-r--r--private/lsa/server/services.c458
1 files changed, 458 insertions, 0 deletions
diff --git a/private/lsa/server/services.c b/private/lsa/server/services.c
new file mode 100644
index 000000000..acc426f6f
--- /dev/null
+++ b/private/lsa/server/services.c
@@ -0,0 +1,458 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ services.c
+
+Abstract:
+
+ This is the service dispatcher for the security process. It contains
+ the service dispatcher initialization routine and the routines to
+ load the DLL for the individual serices and execute them.
+
+Author:
+
+ Rajen Shah (rajens) 11-Apr-1991
+
+[Environment:]
+
+ User Mode - Win32
+
+Revision History:
+
+ 11-Apr-1991 RajenS
+ created
+ 27-Sep-1991 JohnRo
+ More work toward UNICODE.
+ 24-Jan-1991 CliffV
+ Converted to be service dispatcher for the security process.
+
+--*/
+
+//
+// INCLUDES
+//
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <lmcons.h>
+#include <lmerr.h> // NERR_ and ERROR_ equates.
+#include <lmsname.h>
+#include <winsvc.h>
+#include <crypt.h>
+#include <ntsam.h>
+#include <logonmsv.h>
+
+#if DBG
+
+#define IF_DEBUG() if (TRUE)
+
+#else
+
+#define IF_DEBUG() if (FALSE)
+
+#endif
+
+#define IN_RANGE(SomeValue, SomeMin, SomeMax) \
+ ( ((SomeValue) >= (SomeMin)) && ((SomeValue) <= (SomeMax)) )
+
+//
+// SET_SERVICE_EXITCODE() sets the SomeApiStatus to NetCodeVariable
+// if it is within the NERR_BASE and NERR_MAX range. Otherwise,
+// Win32CodeVariable is set.
+//
+#define SET_SERVICE_EXITCODE(SomeApiStatus, Win32CodeVariable, NetCodeVariable) \
+ { \
+ if ((SomeApiStatus) == NERR_Success) { \
+ (Win32CodeVariable) = NO_ERROR; \
+ (NetCodeVariable) = NERR_Success; \
+ } else if (! IN_RANGE((SomeApiStatus), MIN_LANMAN_MESSAGE_ID, \
+ MAX_LANMAN_MESSAGE_ID)) { \
+ (Win32CodeVariable) = (DWORD) (SomeApiStatus); \
+ (NetCodeVariable) = (DWORD) (SomeApiStatus); \
+ } else { \
+ (Win32CodeVariable) = ERROR_SERVICE_SPECIFIC_ERROR; \
+ (NetCodeVariable) = (DWORD) (SomeApiStatus); \
+ } \
+ }
+
+
+typedef DWORD (*PNETLOGON_MAIN) ( \
+ IN DWORD dwNumServicesArgs, \
+ IN LPTSTR *lpServiceArgVectors \
+ );
+
+
+VOID
+DummyControlHandler(
+ IN DWORD opcode
+ )
+/*++
+
+Routine Description:
+
+ Process and respond to a control signal from the service controller.
+
+Arguments:
+
+ opcode - Supplies a value which specifies the action for the Netlogon
+ service to perform.
+
+Return Value:
+
+ None.
+
+ NOTE : this is a dummy handler, used to uninstall the netlogon service
+ when we unable to load netlogon dll.
+--*/
+{
+
+ IF_DEBUG() {
+ DbgPrint( "[Security Process] in control handler\n");
+ }
+
+ return;
+}
+
+
+VOID
+SrvLoadNetlogon (
+ IN DWORD dwNumServicesArgs,
+ IN LPTSTR *lpServiceArgVectors
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is the 'main' routine for the netlogon service. It loads
+ Netlogon.dll (which contains the remainder of the service) and
+ calls the main entry point there.
+
+Arguments:
+
+ dwNumServicesArgs - Number of arguments in lpServiceArgVectors.
+
+ lpServiceArgVectors - Argument strings.
+
+Return Value:
+
+ return nothing.
+
+Note:
+
+
+--*/
+{
+ NET_API_STATUS NetStatus;
+ HANDLE NetlogonDllHandle = NULL;
+ PNETLOGON_MAIN NetlogonMain;
+ DWORD ReturnStatus;
+
+ SERVICE_STATUS_HANDLE ServiceHandle;
+ SERVICE_STATUS ServiceStatus;
+
+ //
+ // Load netlogon.dll
+ //
+
+ NetlogonDllHandle = LoadLibraryA( "Netlogon" );
+
+ if ( NetlogonDllHandle == NULL ) {
+ NetStatus = GetLastError();
+
+ IF_DEBUG() {
+
+ DbgPrint( "[Security process] "
+ "load library netlogon.dll failed %ld\n", NetStatus );
+ }
+
+ goto Cleanup;
+ }
+
+ //
+ // Find the main entry point for the netlogon service.
+ //
+
+ NetlogonMain = (PNETLOGON_MAIN)
+ GetProcAddress( NetlogonDllHandle, "NlNetlogonMain");
+
+ if ( NetlogonMain == NULL ) {
+ NetStatus = GetLastError();
+
+ IF_DEBUG() {
+
+ DbgPrint( "[Security process] GetProcAddress failed %ld\n",
+ NetStatus );
+ }
+
+ goto Cleanup;
+ }
+
+ //
+ // Call the Netlogon service.
+ //
+
+ ReturnStatus = (*NetlogonMain)(
+ dwNumServicesArgs,
+ lpServiceArgVectors
+ );
+
+ //
+ // Unload the library and return.
+ //
+
+ (VOID) FreeLibrary( NetlogonDllHandle );
+
+ return;
+
+Cleanup:
+
+ if ( NetlogonDllHandle != NULL ) {
+ (VOID) FreeLibrary( NetlogonDllHandle );
+ }
+
+ //
+ // register netlogon to service controller
+ //
+
+ ServiceHandle =
+ RegisterServiceCtrlHandler( SERVICE_NETLOGON, DummyControlHandler);
+
+ if (ServiceHandle != (SERVICE_STATUS_HANDLE) NULL) {
+
+ //
+ // inform service controller that the service can't start.
+ //
+
+ ServiceStatus.dwServiceType = SERVICE_WIN32;
+ ServiceStatus.dwCurrentState = SERVICE_STOPPED;
+ ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
+ SERVICE_ACCEPT_PAUSE_CONTINUE;
+ ServiceStatus.dwCheckPoint = 0;
+ ServiceStatus.dwWaitHint = 0;
+
+ SET_SERVICE_EXITCODE(
+ NetStatus,
+ ServiceStatus.dwWin32ExitCode,
+ ServiceStatus.dwServiceSpecificExitCode
+ );
+
+ if( !SetServiceStatus( ServiceHandle, &ServiceStatus ) ) {
+
+ IF_DEBUG() {
+
+ DbgPrint( "[Security process] SetServiceStatus failed %ld\n",
+ GetLastError() );
+ }
+ }
+
+ }
+ else {
+
+ IF_DEBUG() {
+
+ DbgPrint( "[Security process] "
+ "RegisterServiceCtrlHandler failed %ld\n",
+ GetLastError() );
+ }
+ }
+
+ return;
+}
+
+
+//
+// Dispatch table for all services. Passed to NetServiceStartCtrlDispatcher.
+//
+// Add new service entries here.
+//
+
+SERVICE_TABLE_ENTRY SecurityServiceDispatchTable[] = {
+ { SERVICE_NETLOGON, SrvLoadNetlogon },
+ { NULL, NULL }
+ };
+
+
+DWORD
+ServiceDispatcherThread (
+ LPVOID Parameter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine synchronizes with the service controller. It waits
+ for the service controller to set the SECURITY_SERVICES_STARTED
+ event then starts up the main
+ thread that is going to handle the control requests from the service
+ controller.
+
+ It basically sets up the ControlDispatcher and, on return, exits from
+ this main thread. The call to NetServiceStartCtrlDispatcher does
+ not return until all services have terminated, and this process can
+ go away.
+
+ It will be up to the ControlDispatcher thread to start/stop/pause/continue
+ any services. If a service is to be started, it will create a thread
+ and then call the main routine of that service.
+
+
+Arguments:
+
+ EventHandle - Event handle to wait on before continuing.
+
+Return Value:
+
+ Exit status of thread.
+
+Note:
+
+
+--*/
+{
+ DWORD WaitStatus;
+ HANDLE EventHandle;
+ BOOL StartStatus;
+
+ //
+ // Create an event for us to wait on.
+ //
+
+ EventHandle = CreateEventW( NULL, // No special security
+ TRUE, // Must be manually reset
+ FALSE, // The event is initially not signalled
+ SECURITY_SERVICES_STARTED );
+
+ if ( EventHandle == NULL ) {
+ WaitStatus = GetLastError();
+
+ //
+ // If the event already exists,
+ // the service controller already created it. Just open it.
+ //
+
+ if ( WaitStatus == ERROR_ALREADY_EXISTS ) {
+
+ EventHandle = OpenEventW( EVENT_ALL_ACCESS,
+ FALSE,
+ SECURITY_SERVICES_STARTED );
+
+ if ( EventHandle == NULL ) {
+ WaitStatus = GetLastError();
+
+ IF_DEBUG() {
+
+ DbgPrint("[Security process] OpenEvent failed %ld\n",
+ WaitStatus );
+ }
+
+ return WaitStatus;
+ }
+
+ } else {
+
+ IF_DEBUG() {
+ DbgPrint("[Security process] CreateEvent failed %ld\n",
+ WaitStatus);
+ }
+
+ return WaitStatus;
+ }
+ }
+
+
+ //
+ // Wait for the service controller to come up.
+ //
+
+ WaitStatus = WaitForSingleObject( (HANDLE) EventHandle, (DWORD) -1 );
+ (VOID) CloseHandle( EventHandle );
+
+ if ( WaitStatus != 0 ) {
+
+ IF_DEBUG() {
+
+ DbgPrint("[Security process] WaitForSingleObject failed %ld\n",
+ WaitStatus );
+ }
+
+ return WaitStatus;
+ }
+
+
+
+ //
+ // Call NetServiceStartCtrlDispatcher to set up the control interface.
+ // The API won't return until all services have been terminated. At that
+ // point, we just exit.
+ //
+
+ StartStatus =
+ StartServiceCtrlDispatcher ( SecurityServiceDispatchTable );
+
+ IF_DEBUG() {
+
+ DbgPrint("[Security process] return from StartCtrlDispatcher %ld \n",
+ StartStatus );
+ }
+
+ return StartStatus;
+
+ UNREFERENCED_PARAMETER(Parameter);
+}
+
+
+NTSTATUS
+ServiceInit (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This is a main routine for the service dispatcher of the security process.
+ It starts up a thread responsible for coordinating with the
+ service controller.
+
+
+Arguments:
+
+ NONE.
+
+Return Value:
+
+ Status of the thread creation operation.
+
+Note:
+
+
+--*/
+{
+ DWORD ThreadId;
+ HANDLE ThreadHandle;
+
+ //
+ // The control dispatcher runs in a thread of its own.
+ //
+
+ ThreadHandle = CreateThread(
+ NULL, // No special thread attributes
+ 0, // No special stack size
+ &ServiceDispatcherThread,
+ NULL, // No special parameter
+ 0, // No special creation flags
+ &ThreadId);
+
+ if ( ThreadHandle == NULL ) {
+ return (NTSTATUS) GetLastError();
+ }
+
+ return STATUS_SUCCESS;
+}