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.
736 lines
17 KiB
736 lines
17 KiB
/*++
|
|
|
|
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
|