RAS API програмування

Антонянц Вадим Валерійович

Останнім часом, я отримую багато листів з проханням пояснити на конкретному
прикладі, принцип побудови програм заміняють собою стандартний засіб дозвону
Windows. Це досить складно зробити просто і зрозуміло, у зв'язку зі специфікою роботи
різних модифікацій цієї популярної операційної системи. Для кожного випадку
необхідний індивідуальний підхід, але основні алгоритми функціонування
незмінні. На початку 1999 року, я опублікував у Usenet ~ е, деякі міркування з
цього приводу в місці з простим прикладом написання програми здійснює дозвон і
з'єднання з провайдером. Не беруся стверджувати, що такий підхід єдино правильний.
Але як мені здається даний приклад, дозволяє відповісти на безліч питань з програмування
RASAPI.

Деякий час тому у мене з'явилася проблема з урахуванням часу проведеного в
мережі та додаткового сервісу в плані автоматичної конфігурації модему в залежності
від часу доби. Хочу пояснити, що у нас використовується АТС старого типу з механічними
контактами і тому якість з'єднання з провайдером змінюється за певним
законом. З 10-12 години дня до 22-24 годин ймовірність рас з'єднання в процесі роботи
приблизно зростає, а в інший час таких проблем зазвичай не виникає. Виходом
з ситуації було додаткове програмування модему за допомогою АТ команд. Те
Тобто створюється кілька з'єднань в телефонній книзі Windows і в залежності від
часу доби дозваніваніе до провайдера здійснюється за певною закономірності.
З'явилося бажання все це автоматизувати, але підходящої програми "дзвонилки"
виявити не вдалося. Тоді було прийнято рішення написати програму що дозволяє
вирішити всі ці та деякі інші поставлені завдання по телефонному з'єднанню з
провайдером.

Початковий варіант ескізу програми був написаний мною на Microsoft С, завдяки
достатньому великій кількості інформації за Remote Access Service (Віддалене Обслуговування Доступу)
і цілком пристойною довідкової документації в стандартному постачанні Visual C + + V5.0.
Однак, такі фактори як "роздутість" коду нескінченні поневіряння при вираженні
оптимізованого алгоритму функціонування і нарешті великі витрати часу на складання
красивого інтерфейсу користувача привели мене до думки про написання програми в середовищі
розробки Delphi 4. Спочатку це здавалося досить складним завданням, оскільки в Delphi
відсутній модуль прототипів RASAPI функцій, але невелика їх кількість і логічна
простота складання подібних прототипів в об'єктному Паскалі Delphi дозволило в короткий
термін згрупувати необхідні дані.

Передбачуваний алгоритм роботи програми "дзвонилки" досить простий.
Є два шляхи проведення з'єднання з віддаленим сервером. Перший шлях – це коли
програма не інтегрована в операційну систему і працює автономно. Тобто вона
за допомогою RAS API функцій одержує інформацію про список поточних з'єднань і після
вибору необхідного, починає процес телефонного з'єднання аж до кінцевого
результату. Системна програма "дзвонилка" в цьому випадки може бути
активізована незалежно від вашої програми і за наявності вбудованої функції обліку
часу проведеного в мережі може сучіться, що при з'єднанні з її допомогою облік
часу буде порушений. Правда на цей рахунок, є застереження, що при невпинному
циклі перевірки існуючих з'єднань всe-таки можна проводити досить точний
облік часу проведеного в Інтернеті. Але при цьому значно витрачаються ресурси
системи. Другий шлях – дещо складніше, але він найбільш цікавий з точки
зору алгоритму реалізації. За допомогою функцій RAS API, програма інтегрується в
систему і в деяких випадках дозволяє замінювати собою системну "звонілку".
При необхідності проведення з'єднання, система проектує в адресний простір
викликає процесу вашу DLL, викликаючи функцію повторного виклику, прототип якої
заздалегідь відомий і стандартизований. У момент виклику даної функції з DLL, в
ній може бути створений новий потік або потоки в поточному просторі викликає
процесу для створення інтерфейсу програми "дзвонилки". Так само, з цієї DLL
може бути створено новий об'єкт ядра типу процес зі своїми 4 Гб віртуального адресного
простору, в якому породжується головний потік окремої програми "дзвонилки".

У кінцевому підсумку я зупинився на другому варіанті, де з моєї DLL викликається
окрема програма "дзвонилка", яка запускається в окремому процесі та
керована з функції повторного виклику DLL різноманітними способами. Залишилася справа
за малим – вибором способу обміну даними між додатками. Автоматизація OLE і
створення та впровадження COM об'єктів були відкинуті відразу з за великих і безпідставних
витрат системних ресурсів і пам'яті. Залишалося використовувати трохи застарілий
спосіб динамічний обміну даними між додатками DDE. Ось тут і почалися казуси.
При застосуванні бібліотеки DDEML при виконанні транзакції XTYP_REQUEST (запит
клієнтом на повернення даних з сервера) необхідно створити в DLL спеціальну
функцію повторного виклику, у яку при запиті клієнта, сервер повинен повертати
дані. Хочу відразу зазначити, що тут мова йде тільки про асинхронних транзакціях,
так як функція повторного виклику DLL повинна повертати додатком її запитами,
результат роботи вашої програми "дзвонилки" і у випадку невдачі викликати
системну "звонілку". Так от, якщо проводилася вищеописана транзакція
і не було виходу з функції повторного виклику, відправка даних сервера клієнту не
вироблялася (у свою функцію повторного виклику). Причому це відбувалося і в бібліотеці
написаної в Microsoft С. Не допомагало та ж відкриття нового потоку та створення обробника
транзакції в ньому. Причиною тому, на моє глибоке переконання, було специфіка роботи Windows
98 (в Windows NT все працювало чудово). Рішенням проблеми залишалося використання
DDE без застосування бібліотеки Ddeml.dll і віконні спілкування на рівні системи. Перший
шлях через свою неефективність (з гармати по горобцях), був відкинутий відразу і обмін
даними між бібліотекою та програмою "дзвонилки" проводився за допомогою
віконних повідомлень (Window Messages).

Тепер я хочу коротко описати алгоритм функціонування моєї програми. У випадку
інтеграції програми в систему, при потребі з'єднання з віддаленим сервером браузер,
наприклад Internet Explorer, проектує DLL в сої адресний простір (динамічна
завантаження) і викликає функцію повторного виклику. Інформацію про ім'я функції і повному
шляху до DLL він отримує в процесі інтеграції програми. У початковому етапі виклику функції
в DLL створюється новий потік, в якому реєструється новий клас вікна і створюється
невидиме користувачеві приховане вікно. Функція обробник віконних повідомлень реєструє
тільки два типи віконних повідомлень – це WM_DESTROY і WM_USER. Перше необхідно для
деструктуризації вікна, а друге, безпосередньо для отримання даних з програми
сервера. Надалі, проводиться пошук вікна програми "дзвонилки" в
системі і у разі його відсутності породжується новий окремий процес, в головному
потоці якого йде виконання Bашей програми. Подальший обмін даними між
додатками відбувається на рівні віконних повідомлень. При вдалому або невдалому
результаті дозвону функція повторного виклику повертає в програму замовник
відповідне значення і залежно від цього, викликається чи не викликається
системна програма "дзвонилка". При вивантаженні DLL з пам'яті приховане вікно
отримує повідомлення WM_DESTROY, тим самим, коректно завершуючи потік. Хочу особливо відзначити,
що для спрощення коду програми у програмі-сервері (написаної в Delphi) не створюється
додаткове вікно, а всі віконні повідомлення обробляються в головному вікні програми.
Для цього була визначена процедура базового класу VCL WndProc. Даний спосіб не
є досить коректним, проте при правильному розумінні специфіки роботи VCL
(Visual components library) значно спрощує програмування.

Наведені мною тут вихідні коди не є закінченою програмою, а являють
собою випробувальний полігон для перевірки різноманітних алгоритмів і їх способів
реалізації. Тому, буду дуже радий будь-якої інформації і готовий підтримати будь-яке обговорення
цього питання. Тільки є велике прохання, не надсилати повідомлення подібного типу – "На
навіщо тобі це все здався. Вже така прога існує …".

PS: Увага! Якщо в середовищі розробки Delphi4 буде відкрита сторінка з Maim.pas,
робота відладжується програми буде порушена оскільки це вікно буде помилково знайдена
функцією API FindWindow. Тому перед налагодженням програми закрийте цю сторінку.

Завантажити приклад (17 Кб)

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*