|
|
/*++
Copyright(c) 1995 Microsoft Corporation
MODULE NAME init.c
ABSTRACT Initialization for the implicit connection service.
AUTHOR Anthony Discolo (adiscolo) 08-May-1995
REVISION HISTORY
--*/
#define UNICODE
#define _UNICODE
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <stdlib.h>
#include <windows.h>
#include <stdio.h>
#include <wchar.h>
#include <winsock.h>
#include <npapi.h>
#include <ipexport.h>
#include <ras.h>
#include <rasman.h>
#include <acd.h>
#include <tapi.h>
#define DEBUGGLOBALS
#include <debug.h>
#include <rasuip.h>
#include "rasprocs.h"
#include "table.h"
#include "addrmap.h"
#include "netmap.h"
#include "imperson.h"
#include "tapiproc.h"
#include "access.h"
#include "misc.h"
#include "rtutils.h"
//
// Name of the event rasman.dll
// signals whenever a connection
// is created/destroyed.
//
#define CONNECTION_EVENT L"RasConnectionChangeEvent"
//
// Global variables
//
#if DBG
DWORD AcsDebugG = 0x0; // flags defined in debug.h
#endif
DWORD dwModuleUsageG = 0; HANDLE hNewLogonUserG = NULL; // new user logged into the workstation
HANDLE hNewFusG = NULL; // FUS caused a new user to get the console
HANDLE hPnpEventG = NULL; // Pnp event notification
HANDLE hLogoffUserG = NULL; // user logged off workstation
HANDLE hLogoffUserDoneG = NULL; // HKEY_CURRENT_USER flushed
HANDLE hTerminatingG = NULL; // service is terminating
HANDLE hSharedConnectionG = NULL; // dial shared connection
HANDLE hAddressMapThreadG = NULL; // AcsAddressMapThread()
extern HANDLE hAutodialRegChangeG;
HINSTANCE hinstDllG; LONG g_lRasAutoRunning = 0;
HANDLE g_hLogEvent = NULL;
DWORD g_dwCritSecFlags = 0;
//
// External variables
//
extern HANDLE hAcdG; extern IMPERSONATION_INFO ImpersonationInfoG; extern CRITICAL_SECTION csRasG; extern HKEY hkeyCUG; extern CRITICAL_SECTION csDisabledAddressesLockG;
DWORD PnpRegister( IN BOOL fRegister);
BOOLEAN WINAPI InitAcsDLL( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
/*++
DESCRIPTION Initialize the implicit connection DLL. Dynamically load rasapi32.dll and rasman.dll, and initialize miscellaneous other things.
ARGUMENTS hinstDLL:
fdwReason:
lpvReserved:
RETURN VALUE Always TRUE.
--*/
{ switch (fdwReason) { case DLL_PROCESS_ATTACH: if (hinstDllG == NULL) hinstDllG = hinstDLL;
break;
case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: break;
case DLL_PROCESS_DETACH: break; } return TRUE; }
DWORD AcsInitialize() { NTSTATUS status; DWORD dwErr, dwcDevices = 0; WSADATA wsaData; UNICODE_STRING nameString; IO_STATUS_BLOCK ioStatusBlock; OBJECT_ATTRIBUTES objectAttributes; DWORD dwThreadId; RasAutoDebugInit(); do { hAcdG = NULL;
g_dwCritSecFlags = 0; //
// Initialize winsock.
//
dwErr = WSAStartup(MAKEWORD(2,0), &wsaData);
if (dwErr) { RASAUTO_TRACE1("AcsInitialize: WSAStartup failed (dwErr=%d)", dwErr); break; }
//
// Load icmp.dll.
//
LoadIcmpDll(); //
// Initialize TAPI.
//
dwErr = TapiInitialize(); if (dwErr) { RASAUTO_TRACE1("AcsInitialize: TapInitialize failed (dwErr=%d)", dwErr); break; }
g_hLogEvent = RouterLogRegister(L"RASAUTO"); if(NULL == g_hLogEvent) { dwErr = GetLastError(); RASAUTO_TRACE1("AcsInitialize: RouterLogRegister failed 0x%x", dwErr); break; } //
// Initialize the name of the implicit
// connection device.
//
RtlInitUnicodeString(&nameString, ACD_DEVICE_NAME); //
// Initialize the object attributes.
//
InitializeObjectAttributes( &objectAttributes, &nameString, OBJ_CASE_INSENSITIVE, (HANDLE)NULL, (PSECURITY_DESCRIPTOR)NULL); //
// Open the automatic connection device.
//
status = NtCreateFile( &hAcdG, FILE_READ_DATA|FILE_WRITE_DATA, &objectAttributes, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN_IF, 0, NULL, 0); if (status != STATUS_SUCCESS) { RASAUTO_TRACE1( "AcsInitialize: NtCreateFile failed (status=0x%x)", status);
dwErr = ERROR_BAD_DEVICE; break; } //
// Create the event that userinit.exe signals
// when a new user logs into the workstation.
// Note we have to create a security descriptor
// to make this event accessible by a normal user.
//
dwErr = InitSecurityAttribute(); if (dwErr) { RASAUTO_TRACE1( "AcsInitialize: InitSecurityAttribute failed (dwErr=0x%x)", dwErr); break; } //
// Create the events that are used for login/logout
// notification. userinit.exe signals RasAutodialNewLogonUser
// winlogon signals RasAutodialLogoffUser, and rasauto.dll
// signals RasAutodialLogoffUserDone when it has completed
// flushing HKEY_CURRENT_USER.
//
hNewLogonUserG = CreateEvent(&SecurityAttributeG, FALSE, FALSE, L"RasAutodialNewLogonUser"); if (hNewLogonUserG == NULL) { RASAUTO_TRACE("AcsInitialize: CreateEvent (new user) failed"); dwErr = GetLastError(); break; } hNewFusG = CreateEvent(&SecurityAttributeG, FALSE, FALSE, NULL); if (hNewFusG == NULL) { RASAUTO_TRACE("AcsInitialize: CreateEvent (FUS) failed"); dwErr = GetLastError(); break; } hPnpEventG= CreateEvent(&SecurityAttributeG, FALSE, FALSE, NULL); if (hPnpEventG == NULL) { RASAUTO_TRACE("AcsInitialize: CreateEvent (hPnpEventG) failed"); dwErr = GetLastError(); break; } hLogoffUserG = CreateEvent(&SecurityAttributeG, FALSE, FALSE, L"RasAutodialLogoffUser"); if (hLogoffUserG == NULL) { RASAUTO_TRACE("AcsInitialize: CreateEvent (logoff) failed"); dwErr = GetLastError(); break; } hLogoffUserDoneG = CreateEvent(&SecurityAttributeG, FALSE, FALSE, L"RasAutodialLogoffUserDone"); if (hLogoffUserDoneG == NULL) { RASAUTO_TRACE("AcsInitialize: CreateEvent (logoff done) failed"); dwErr = GetLastError(); break; } //
// Create an event to tell us when to dial the shared connection
//
hSharedConnectionG = CreateEventA(&SecurityAttributeG, FALSE, FALSE, RAS_AUTO_DIAL_SHARED_CONNECTION_EVENT); if (hSharedConnectionG == NULL) { RASAUTO_TRACE("AcsInitialize: CreateEvent failed"); dwErr = GetLastError(); break; } //
// Create an event to give to rasapi32 to let
// us know when a new RAS connection has been
// created or destroyed.
//
hConnectionEventG = CreateEvent(NULL, FALSE, FALSE, NULL); if (hConnectionEventG == NULL) { RASAUTO_TRACE("AcsInitialize: CreateEvent failed"); dwErr = GetLastError(); break; } //
// Create the event all threads wait
// that notify them of termination.
//
hTerminatingG = CreateEvent(NULL, TRUE, FALSE, NULL); if (hTerminatingG == NULL) { RASAUTO_TRACE("AcsInitialize: CreateEvent failed"); dwErr = GetLastError(); break; } //
// Initialize impersonation structures
//
dwErr = InitializeImpersonation(); if (dwErr) { RASAUTO_TRACE1( "AcsInitialize: InitializeImpersonation failed (dwErr=0x%x)", dwErr); break; } //
// Create critical section that protects the
// RAS module structures.
//
RasInitializeCriticalSection(&csRasG, &dwErr);
if(dwErr != ERROR_SUCCESS) { break; }
g_dwCritSecFlags |= RASAUTO_CRITSEC_RASG;
RasInitializeCriticalSection(&csDisabledAddressesLockG, &dwErr);
if(dwErr != ERROR_SUCCESS) { break; }
g_dwCritSecFlags |= RASAUTO_CRITSEC_DISABLEDADD;
//
// Create a thread to manage the addresses stored
// in the registry.
//
if (!InitializeAddressMap()) { RASAUTO_TRACE("AcsInitialize: InitializeAddressMap failed"); dwErr = ERROR_OUTOFMEMORY; break; } if (!InitializeNetworkMap()) { RASAUTO_TRACE("AcsInitialize: InitializeNetworkMap failed"); dwErr = ERROR_OUTOFMEMORY; break; } hAddressMapThreadG = CreateThread( NULL, 10000L, (LPTHREAD_START_ROUTINE)AcsAddressMapThread, 0, 0, &dwThreadId); if (hAddressMapThreadG == NULL) { dwErr = GetLastError(); RASAUTO_TRACE1( "AcsInitialize: CreateThread failed (error=0x%x)", dwErr); break; }
// XP 364593
//
// Register for pnp not. Ignore the return value -- if we error,
// then we simply wont react when a lan adapter comes/goes.
// It's not worth letting that stop us.
//
PnpRegister(TRUE);
return ERROR_SUCCESS; } while(FALSE);
//
// Cleanup in case of error.
//
TapiShutdown();
if(g_dwCritSecFlags & RASAUTO_CRITSEC_RASG) { DeleteCriticalSection(&csRasG); g_dwCritSecFlags &= ~(RASAUTO_CRITSEC_RASG); }
if(g_dwCritSecFlags & RASAUTO_CRITSEC_DISABLEDADD) { DeleteCriticalSection(&csDisabledAddressesLockG); g_dwCritSecFlags &= ~(RASAUTO_CRITSEC_DISABLEDADD); }
if(NULL != g_hLogEvent) { RouterLogDeregister(g_hLogEvent); g_hLogEvent = NULL; }
if(NULL != hAcdG) { CloseHandle(hAcdG); hAcdG = NULL; }
if(NULL != hNewLogonUserG) { CloseHandle(hNewLogonUserG); hNewLogonUserG = NULL; }
if(NULL != hNewFusG) { CloseHandle(hNewFusG); hNewFusG = NULL; }
if(NULL != hPnpEventG) { CloseHandle(hPnpEventG); hPnpEventG = NULL; }
if(NULL != hLogoffUserG) { CloseHandle(hLogoffUserG); hLogoffUserG = NULL; }
if(NULL != hLogoffUserDoneG) { CloseHandle(hLogoffUserDoneG); hLogoffUserDoneG = NULL; }
if(NULL != hSharedConnectionG) { CloseHandle(hSharedConnectionG); hSharedConnectionG = NULL; }
if(NULL != hConnectionEventG) { CloseHandle(hConnectionEventG); hConnectionEventG = NULL; }
if(NULL != hTerminatingG) { CloseHandle(hTerminatingG); hTerminatingG = NULL; }
return dwErr; } // AcsInitialize
VOID AcsTerminate() { //
// Signal other threads to exit.
// The main service controller
// thread AcsDoService() will
// call WaitForAllThreads().
//
SetEvent(hTerminatingG); } // AcsTerminate
VOID WaitForAllThreads() { RASAUTO_TRACE("WaitForAllThreads: waiting for all threads to terminate"); //
// Wait for them to exit.
//
WaitForSingleObject(hAddressMapThreadG, INFINITE); //
// Unload icmp.dll.
//
UnloadIcmpDll(); //
// Cleanup.
//
// PrepareForLongWait();
CloseHandle(hAddressMapThreadG); RASAUTO_TRACE("WaitForAllThreads: all threads terminated"); }
VOID AcsCleanupUser()
/*++
DESCRIPTION Unload all resources associated with the currently logged-in user.
ARGUMENTS None.
RETURN VALUE None.
--*/
{ if(NULL != hkeyCUG) { NtClose(hkeyCUG); hkeyCUG = NULL; } } // AcsCleanupUser
VOID AcsCleanup()
/*++
DESCRIPTION Unload all resources associated with the entire service.
ARGUMENTS None.
RETURN VALUE None.
--*/
{ //
// Stop receiving pnp events
//
PnpRegister(FALSE); //
// Unload per-user resources.
//
// AcsCleanupUser();
//
// We're terminating. Wait for the
// other threads.
//
WaitForAllThreads(); //
// Shutdown TAPI.
//
TapiShutdown(); //
// We've terminated. Free resources.
//
CloseHandle(hAcdG); //
// For now, unload rasman.dll only when
// we are about to go away.
//
//
// Close all event handles
//
if(NULL != hNewLogonUserG) { CloseHandle(hNewLogonUserG); hNewLogonUserG = NULL; }
if(NULL != hNewFusG) { CloseHandle(hNewFusG); hNewFusG = NULL; }
if(NULL != hPnpEventG) { CloseHandle(hPnpEventG); hPnpEventG = NULL; }
if(NULL != hLogoffUserG) { CloseHandle(hLogoffUserG); hLogoffUserG = NULL; }
if(NULL != hLogoffUserDoneG) { CloseHandle(hLogoffUserDoneG); hLogoffUserDoneG = NULL; }
if(NULL != hSharedConnectionG) { CloseHandle(hSharedConnectionG); hSharedConnectionG = NULL; }
if(NULL != hConnectionEventG) { CloseHandle(hConnectionEventG); hConnectionEventG = NULL; }
if(NULL != hTerminatingG) { CloseHandle(hTerminatingG); hTerminatingG = NULL; }
if(NULL != hAutodialRegChangeG) { CloseHandle(hAutodialRegChangeG); hAutodialRegChangeG = NULL; }
if(NULL != g_hLogEvent) { RouterLogDeregister(g_hLogEvent); g_hLogEvent = NULL; }
{ LONG l; l = InterlockedDecrement(&g_lRasAutoRunning); { // DbgPrint("RASAUTO: AcsCleanup - lrasautorunning=%d\n", l);
}
ASSERT(l == 0); }
//
// Revert impersonation before cleaning up
//
RevertImpersonation();
//
// Cleanup impersonation structures
//
CleanupImpersonation();
//
// Uninitialize addressmap
//
UninitializeAddressMap();
if(g_dwCritSecFlags & RASAUTO_CRITSEC_DISABLEDADD) { DeleteCriticalSection(&csDisabledAddressesLockG); g_dwCritSecFlags &= ~(RASAUTO_CRITSEC_DISABLEDADD); }
//
// UninitializeNetworkmap
//
UninitializeNetworkMap(); RasAutoDebugTerm();
UnloadRasDlls();
if(g_dwCritSecFlags & RASAUTO_CRITSEC_RASG) { DeleteCriticalSection(&csRasG); g_dwCritSecFlags &= ~(RASAUTO_CRITSEC_RASG); } } // AcsCleanup
|