Статья взята с сайта rsdn.ru. Искренне надеюсь, что автор не против размещения его статьи здесь.

Routing and Remote Access Server Administration DLL
Назначение, пример приложения

Автор: Певцов Константин aka Rainbow
  • Краткое описание
  • Функции RAS Admin DLL
  • Подключение к RAS
  • Пример приложения

Краткое описание.

Routing and Remote Access Server Administration DLL (далее RAS Admin DLL) служит для подключения к серверу удаленного доступа и выполнения администраторских функций, описанных в DLL. Может применяться для организаций, предоставляющих свои услуги по доступу в Internet с помощью удаленного доступа.Можно отметить три основных задачи, которые можно решить с помощью RAS Admin DLL:


1. Идентифицировать пользователя, дополнительно к стандартной проверке сервера удаленного доступа.
2. Записывать время подключения и отключения пользователей.
3. Принудительно назначать IP адрес пользователю.


Также, при помощи небольших ухищрений можно выполнять практически любые функции. Например, за час, до окончания лимита доступного времени посылать пользователю электронное письмо с предупреждением и т.д.

Возможность использования RAS Admin DLL существует в операционных системах, построенных на базе NT, начиная с WindowsNT 4.0. Но реализация самой DLL для WindowsNT 4.0 и для более поздних операционных систем (Windows 2000/XP) отличается. В данной статье описывается пример создания RAS Admin DLL для Windows 2000/XP. Более подробную информацию можно получить в MSDN.

Функции RAS Admin DLL.

RAS Admin DLL должна содержать определенные функции, которые и будут вызываться сервером удаленного доступа, в зависимости от события.Ниже представлен список этих функций и их краткое описание.

Функции представлены в порядке их вызова в течении одного сеанса работы сервера удаленного доступа.

DWORD APIENTRY MprAdminInitializeDll(VOID)

Вызывается при запуске сервера удаленного доступа и подключении вашей DLL. Эта функция вызывается первой из всех, необходимых для работы RAS Admin DLL. Предназначена для ваших инициализационных действий. Требует возврата NO_ERROR для продолжения работы вашей DLL. Если функция возвращает значение отличное от NO_ERROR, то работа RAS Admin DLL блокируется и сервер удаленного доступа работает в обычном режиме.

 

DWORD APIENTRY MprAdminGetIpAddressForUser(WCHAR *UserName,WCHAR *PortName,DWORD *IpAddress,BOOL *NotifyRelease)
Функция назначения нового IP адреса. При назначении нового IP адреса, NotifyRelease должно принять значение TRUE, а IpAddress – новый IP адрес. Если NotifyRelease равен FALSE, то IP адрес назначается по умолчанию самим сервером удаленного доступа. Вызывается при подключении пользователя к серверу удаленного доступа.

 

BOOL APIENTRY MprAdminAcceptNewConnection(RAS_CONNECTION_0 *pRasc0,RAS_CONNECTION_1 *pRasc1)
Уведомление о новом подключении. Для продолжения работы требует возврата TRUE. Вызывается при подключении пользователя к серверу удаленного доступа. Структуры RAS_CONNECTION_0 и RAS_CONNECTION_1 описаны в MSDN.

BOOL APIENTRY MprAdminAcceptNewLink(RAS_PORT_0 *pRasPort0,RAS_PORT_1 *pRasPort1)
Уведомление об установке связи. Для продолжения работы требует возврата TRUE. Вызывается при подключении пользователя к серверу удаленного доступа. Структуры RAS_PORT_0 и RAS_PORT_1 описаны в MSDN.

void APIENTRY MprAdminLinkHangupNotification(RAS_PORT_0 *pRasPort0, RAS_PORT_1 *pRasPort1)
Уведомление о разрыве связи. Вызывается при отключении пользователя от сервера удаленного доступа.

void APIENTRY MprAdminConnectionHangupNotification(RAS_CONNECTION_0 *pRasc0,RAS_CONNECTION_1 *pRasc1)
Уведомление о разрыве соединения. Вызывается при отключении пользователя от сервера удаленного доступа.

void APIENTRY MprAdminReleaseIpAddress(WCHAR *UserName,WCHAR *PortName,DWORD *IpAddress)
Функция освобождения IP адреса. Вызывается при отключении пользователя от сервера удаленного доступа только при принудительном назначении IP адреса.

DWORD APIENTRY MprAdminTerminateDll(VOID)
Вызывается при выключении сервера.


ПРИМЕЧАНИЕ:
В MSDN присутствует некоторая неточность при описании этих функций. Дело в том, что в MSDN отсутствуют типы вызовов этих функций, т.е. отсутствует признак APIENTRY (_stdcall). По умолчанию же MSVC генерирует код с _cdecl вызовами.

Из вышеописанных функций нельзя вызывать другие RAS администраторские функции.

Подключение к RAS.

Для регистрации вашей RAS Admin DLL в системе и подключении ее к RAS, необходимо прописать соответствующий ключ в реестре. Для простоты можно создать простой reg файл:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\RAS\AdminDll]
"DisplayName"="ras admin dll"
"DLLPath"="c:\\rasdll\\rasdll.dll"
DisplayName – название вашей dll. Никакой существенной роли не играет.DLLPath – полный путь к вашей dll.Сервер удаленного доступа не подключит вашу DLL, если в ней реализованы не все требуемые функции и если отсутствует корректная запись в системном реестре.

Пример приложения.

Для примера можно создать DLL’ку, которая будет, в зависимости от пользователя будет учитывать или не учитывать время подключения к серверу и, при учете времени, будет за какое-то определенное время до окончания лимита, посылать электронное письмо с предупреждением на ящик пользователя.Для полноценной программы необходимы модули работы с базами данных и с сокетами. В примере они опущены, чтобы не загромождать код.

HANDLE hPortZ; // порт

DWORD APIENTRY MprAdminInitializeDll(VOID)
{
// Здесь можно поставить проверку на доступность базы данных, считывание конфигурации, инициализацию переменных и т.д.
return NO_ERROR;
}

DWORD APIENTRY MprAdminGetIpAddressForUser(WCHAR *UserName,WCHAR *PortName,DWORD *IpAddress,BOOL *NotifyRelease)
{
// IP адрес назначается самим сервером
NotifyRelease = FALSE;
return NO_ERROR;
}

BOOL APIENTRY MprAdminAcceptNewConnection(RAS_CONNECTION_0 *pRasc0,RAS_CONNECTION_1 *pRasc1)
{
// в процедуре FindNameUser происходит работа с базой данных – поиск пользователя и возврат в соответствии с результатом
switch (FindNameUser(pRasc0->wszUserName))
{
case 0: // ошибка работы с базой данных
nowork = true;
return FALSE;
break;
case 1: // работать без таймера
createtimer = false;
break;
case 2: // исчерпатн лимит времени
return FALSE;
break;
case 3: // работать с таймером
// создать поток для отсчета времени
hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)TProc,0,0,&dwThreadId);
if (hThread == NULL)
{
return FALSE;
break;
}
// создать поток для отправки электронного письма
hThreadMail = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)TProcMail,0,0,&dwThreadIdMail);
if (hThreadMail == NULL)
{
return FALSE;
break;
}
createtimer = true;
break;
}
return TRUE;
}

BOOL APIENTRY MprAdminAcceptNewLink(RAS_PORT_0 *pRasPort0,RAS_PORT_1 *pRasPort1)
{
hPortZ = pRasPort0->hPort;
return TRUE;
}

void APIENTRY MprAdminLinkHangupNotification(RAS_PORT_0 *pRasPort0, RAS_PORT_1 *pRasPort1)
{
}

void APIENTRY MprAdminReleaseIpAddress(WCHAR *UserName,WCHAR *PortName,DWORD *IpAddress)
{
}

void APIENTRY MprAdminConnectionHangupNotification(RAS_CONNECTION_0 *pRasc0,RAS_CONNECTION_1 *pRasc1)
{
if (createtimer == true)
{
// если поток подсчета времени не завершен, то принудительно завершить его
TerminateThread(hThread,0);
CloseHandle(hThread);
// если поток для отправки почты не завершен, то принудительно завершить его
TerminateThread(hThreadMail,0);
CloseHandle(hThreadMail);
createtimer = false;
}
// Здесь можно поставить запись в базу информации о продолжительности подключения и т.д.
}

DWORD APIENTRY MprAdminTerminateDll(VOID)
{
// Здесь можно поставить завершение работы с базой данных и т.д.
return NO_ERROR;
}

// поток подсчитывающий время и отключающий пользователя
DWORD WINAPI TProc(LPVOID lpar)
{
MPR_SERVER_HANDLE ServerHandle; // timeonline – лимит времени пользователя
Sleep(timeonline*1000); // тормозим поток на доступное время работы
MprAdminServerConnect(NULL,&ServerHandle); // подключаемся к серверу
MprAdminPortClearStats(ServerHandle,hPortZ); // сбрасываем статистику порта
MprAdminPortReset(ServerHandle,hPortZ); // сбрасываем порт
MprAdminPortDisconnect(ServerHandle,hPortZ); // разрываем соеденение
MprAdminServerDisconnect(ServerHandle); // отключаемся от сервера ExitThread(0);
return 0;
}// поток отправляющий предупредительное письмо пользователю
DWORD WINAPI TProcMail(LPVOID lpar)
{
// проверка на доступное время подключения
// timeonline – лимит времени пользователя
// interval – интервал в секундах, перед которым посылать пиедупреждение пользователю
if (timeonline > interval)
{
// доступное время больше минимального интервала
Sleep((timeonline - interval)*1000); // тормозим поток
SendMail(); // посылаем электронное письмо
ExitThread(0);
}
else
{
// доступное время меньше интервала, завершаем поток
ExitThread(0);
}
return 0;
}

 


С уважением ваш ToshibaNT :)


 
   
...[CopyRights & Design: ToshibaNT 2004]...
 
Хостинг от uCoz