Операционная система Microsoft Windows 3.1 для программиста. Дополнительные главы

       

Файл wast\wastdrv.cpp


// ====================================================== // Загружаемый драйвер wastdrv.dll // Версия 1.0 // Используется совместно с приложением wast.exe // и VxD-драйвером VXDSRV.386 версии 1.1 // ------------------------------------------------------ // Copyright (C) 1995 Alexandr Frolov // ====================================================== #define STRICT #include <windows.h>
#include <mem.h>
#include <string.h>
#include "wastdrv.hpp" #include "wastvxd.hpp"

extern "C" LRESULT CALLBACK _export DriverProc(DWORD dwDiverId, HDRVR hDriver, UINT msg, LPARAM lParam1, LPARAM lParam2);

extern "C" void FAR PASCAL _export WinAppStart(WORD wVxDVersion);

BOOL RegisterTask(HTASK hTask);
void UnregisterTask(VXDAPI vxdEntry);

int CALLBACK _export DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam);

void AutoStartWAST(BOOL);

DWORD dwRc = 0L;

// Точка входа API VxD-драйвера VXDAPI vxdApi = NULL;

// Идентификатор задачи приложения wast.exe HTASK hTaskWAST = NULL;

// Буфер для передачи информации о запукаемой // программе BYTE szCallbackBuf[350];

// Очередь запросов на запуск программ из VM MS-DOS BYTE szCmd[6][350];

// Номер строки параметров в массиве szCmd int nCmdLine = 0;

// Флаг регистрации приложения wast.exe BOOL fTaskRegistered = FALSE;



HINSTANCE hMod; char szDriverName[] = "wastdrv"; char szTemp[80];

// ======================================================== // Функция LibMain // ======================================================== #pragma argsused int FAR PASCAL LibMain(HINSTANCE hModule, WORD wDataSegment, WORD wHeapSize, LPSTR lpszCmdLine) { hMod = hModule;

// Получаем точку входа API VxD-драйвера vxdApi = vxdGetDeviceAPI(VXD_ID);
return TRUE; }

// ======================================================== // Функция WEP // ======================================================== #pragma argsused int FAR PASCAL WEP(int bSystemExit) { // Если выгружается из памяти DLL-библиотека, // содержащая загружаемый драйвер, // выполняем отключение VxD-драйвера if(vxdApi != NULL) { if(fTaskRegistered) UnregisterTask(vxdApi);
} return 1; }




// ======================================================== // Функция обратного вызова WinAppStart // ======================================================== extern "C" void FAR PASCAL _export WinAppStart(WORD wVxDVersion) { if(wVxDVersion != 0x0101) return;

_fmemcpy((LPVOID)szCmd[nCmdLine], (LPVOID)szCallbackBuf, 65 + 256);

PostAppMessage(hTaskWAST, WM_STARTWINAPP, 0, (LPARAM)szCmd[nCmdLine]);

nCmdLine++; if(nCmdLine >
5) nCmdLine = 0; }

// ======================================================== // Функция RegisterTask // Регистрация приложения wast.exe // ======================================================== BOOL RegisterTask(HTASK hTask) { if(vxdApi == NULL) return FALSE;

// Устанавливаем флаг регистрации fTaskRegistered = TRUE;

// Сохраняем идентификатор окна hTaskWAST = hTask;

// Вычисляем компоненты адреса функции обратного вызова unsigned sel = SELECTOROF((LPVOID)WinAppStart);
unsigned off = OFFSETOF((LPVOID)WinAppStart);

// Вычисляем компоненты адреса буфера szCallbackBuf unsigned bsel = SELECTOROF(szCallbackBuf);
unsigned boff = OFFSETOF(szCallbackBuf);

// Регистрируем функцию обратного вызова и // буфер szCallbackBuf в VxD-драйвере

asm mov dx, sel asm mov cx, off asm mov si, bsel asm mov di, boff asm mov ax, vxdapiRegisterTask (*vxdApi)();

return TRUE; }

// ======================================================== // Функция UnregisterTask // Отключение VxD-драйвера // ======================================================== void UnregisterTask(VXDAPI vxdEntry) { if(vxdApi == NULL) return;

// Сбрасываем флаг регистрации fTaskRegistered = FALSE;

asm mov ax, vxdapiUnregisterTask (*vxdEntry)();
}

// ======================================================== // Функция vxdGetDeviceAPI // Получение адреса точки входа API для // VxD-драйвера, идентификатор которого // задан параметром vxd_id // ======================================================== VXDAPI vxdGetDeviceAPI(unsigned short vxd_id) { unsigned axreg, dxreg;

asm push ax asm push bx asm push di asm push es



asm mov ax, 0x1684 asm mov bx, vxd_id asm xor di, di asm mov es, di asm int 0x2f asm mov ax, di asm mov dx, es

asm pop es

asm mov axreg, ax asm mov dxreg, dx

asm pop di asm pop bx asm pop ax

return((VXDAPI)MAKELP(dxreg, axreg));
}

// ======================================================== // DriverProc // Функция загружаемого драйвера // ======================================================== extern "C" LRESULT CALLBACK _export DriverProc( DWORD dwDiverId, // идентификатор драйвера HDRVR hDriver, // идентификатор, который // используется для обращения к драйверу UINT msg, // код сообщения LPARAM lParam1, // первый параметр сообщения LPARAM lParam2) // второй параметр сообщения { switch(msg) { // Регистрация окна приложения wast.exe case UDRV_REGISTERTASK: { // Если виртуальный драйвер не загружен, // возвращаем признак ошибки FALSE if(vxdApi == NULL) { dwRc = (DWORD)FALSE; break; }

// Выполняется только в том случае, если // разрешен запуск приложений Windows из // командной строки MS-DOS if(GetPrivateProfileInt(szDriverName, "Enable", 0, "system.ini")) { dwRc = (DWORD)RegisterTask((HTASK)lParam1);
} break; }

// Отмена регистрации приложения wast.exe case UDRV_UNREGISTERTASK: { if(fTaskRegistered) UnregisterTask(vxdApi);
break; }

// Загрузка драйвера. Это первое сообщение, которое // получает драйвер case DRV_LOAD: { dwRc = 1l; break; }

// Это сообщение посылается драйверу перед тем, // как драйвер будет выгружен из памяти case DRV_FREE: { dwRc = 1l; break; }

// Открытие драйвера case DRV_OPEN: { dwRc = 1l; break; }

// Закрытие драйвера case DRV_CLOSE: { dwRc = 1l; break; }

// Разблокирование драйвера case DRV_ENABLE: { dwRc = 1l; break; }

// Блокирование драйвера case DRV_DISABLE: { dwRc = 1l; break; }

// Это сообщение посылается при установке драйвера case DRV_INSTALL: { // Создаем раздел [wastdrv] в файле system.ini // В этом разделе создаем строку: "Enable=1" WritePrivateProfileString(szDriverName, "Enable", "1", "system.ini");



// Дописываем имя приложения wast.exe в строке // "load=" раздела [windows] файла win.ini AutoStartWAST(TRUE);

// Запрашиваем перезапуск Windows dwRc = DRVCNF_RESTART; break; }

// Удаление драйвера case DRV_REMOVE: { // Если окно приложения wast.exe было // зарегистрировано, отменяем регистрацию if(fTaskRegistered) UnregisterTask(vxdApi);

// Посылаем приложению wast.exe сообщение // WM_UNLOADWAST, в ответ на которое оно // завершает свою работу if(hTaskWAST != NULL) PostAppMessage(hTaskWAST, WM_UNLOADWAST, 0, 0l);

// Идентификатор задачи wast.exe теперь // недействителен hTaskWAST = NULL;

// В разделе [wastdrv] файла system.ini // заменяем строку "Enable=1" на "Enable=0" WritePrivateProfileString(szDriverName, "Enable", "0", "system.ini");

// Отменяем автоматический запуск wast.exe AutoStartWAST(FALSE);

dwRc = 0l; break; }

// Это сообщение присылается как запрос на // возможность конфигурирования драйвера. // Так как наш драйвер можно конфигурировать, // возвращаем значение 1l case DRV_QUERYCONFIGURE: { dwRc = 1l; break; }

// Конфигурирование драйвера case DRV_CONFIGURE: { // Создаем диалоговую панель конфигурирования dwRc = DialogBox(hMod, "CONFIG", NULL, DlgProc);
break; }

// Все необработанные сообщения необходимо // передать функции DefDriverProc default: { return DefDriverProc(dwDiverId, hDriver, msg, lParam1, lParam2);
} } return dwRc; }

// ====================================================== // Функция DldProc // Обработка сообщений диалоговой панели конфигурирования // ====================================================== #pragma argsused

int CALLBACK _export DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) { static BOOL fWasActive, fChanged;

switch(msg) { case WM_INITDIALOG: { // Определяем текущее состояние строки "Enable=" fWasActive = GetPrivateProfileInt(szDriverName, "Enable", 0, "system.ini");

// В соответствии с этим состоянием отмечаем // переключатель, управляющий возможностью запуска // приложений Windows из командной строки MS-DOS CheckDlgButton(hdlg, ID_ENABLE, fWasActive);



return TRUE; }

case WM_COMMAND: { switch(wParam) { case IDOK: { // Флаг изменения режима работы драйвера // при его конфигурировании fChanged = TRUE;

// Если переключатель находится во включенном // состоянии, разрешаем работу драйвера if(IsDlgButtonChecked(hdlg, ID_ENABLE)) { if(fWasActive) fChanged = FALSE;

// Заносим изменения в файл system.ini WritePrivateProfileString(szDriverName, "Enable", "1", "system.ini");

// Разрешаем автоматический запуск wast.exe AutoStartWAST(TRUE);
}

// Если переключатель находился в выключенном // состоянии, запрещаем работу драйвера else { if(!fWasActive) fChanged = FALSE; WritePrivateProfileString(szDriverName, "Enable", "0", "system.ini");
AutoStartWAST(FALSE);
}

// Если был изменен режим работы драйвера, // запрашиваем перезапуск Windows EndDialog(hdlg, fChanged ? DRVCNF_RESTART : DRVCNF_CANCEL);
return TRUE; }

// Отмена изменения конфигурации case IDCANCEL: { EndDialog(hdlg, DRVCNF_CANCEL);
return TRUE; } } } } return FALSE; }

// ====================================================== // Функция AutoStartWAST // В зависимости от значения параметра эта функция // дописывает имя приложения wast.exe в строке // "load=" раздела [windows] файла win.ini // или наоборот, удаляет имя wast.exe из этой строки // ====================================================== void AutoStartWAST(BOOL fStart) { static LPSTR lpszSubst;

// Получаем строку "load=..." во временный буфер GetProfileString("windows", "load", "", szTemp, 80);

// Ищем в этой строке имя приложения wast.exe lpszSubst = _fstrstr(szTemp, (LPSTR)"wast");

// Если параметр функции равен TRUE, добавляем // имя в строку if(fStart) { // Добавляем только в том случае, если этого // имени там нет if(lpszSubst == NULL) { lstrcat(szTemp, " ");
lstrcat(szTemp, "wast");
} }

// Если параметр функции равен FALSE, удаляем // имя приложения wast.exe из строки else { // Удаляем только в том случае, если это имя // там действительно есть if(lpszSubst != NULL) { _fstrcpy(lpszSubst, lpszSubst + _fstrlen(lpszSubst));
} }



// Сохраняем новое значение строки "load=..." WriteProfileString("windows", "load", szTemp);
}

Функция LibMain загружаемого драйвера аналогична такой же функции DLL-библиотеки d2w.dll. Она получает и сохраняет точку входа виртуального драйвера и дополнительно запоминает в глобальной переменной идентификатор модуля загружаемого драйвера.

Функция WEP отменяет регистрацию при выгрузке драйвера из памяти, вызывая функцию UnregisterTask. Эта функция полностью аналогична функции UnregisterWnd библиотеки d2w.dll, причину изменения названия вы узнаете чуть позже.

Функция WinAppStart выполняет ту же задачу, что и одноименная функция из библиотеки d2w.dll, однако делает она это немного по-другому.

Обратите внимание, что для посылки сообщения приложению wast.exe (аналогичного приложению dos2win.exe) мы использовали вместо функции PostMessage функцию PostAppMessage. Это связано с тем, что приложение wast.exe вообще не создает главного окна, хотя, тем не менее, имеет цикл обработки сообщений! (Разумеется, вы можете использовать и старый метод, использованный в приложении dos2win.exe).

В качестве первого параметра функции PostAppMessage необходимо передать идентификатор задачи wast.exe (а не идентификатор окна, которое, кстати, вообще не существует).

Идентификатор задачи сохраняется в глобальной переменной функцией RegisterTask, которая соответствует функции RegisterWnd библиотеки d2w.dll, но вызывается по-другому. Вызов этой функции выполняется из функции DriverProc при обработке пользовательского сообщения UDRV_REGISTERTASK, посылаемого загружаемому драйверу приложением wast.exe.

Аналогично, обработчик другого пользовательского сообщения UDRV_UNREGISTERTASK вызывает функцию UnregisterTask, действие которой полностью аналогично действию функции UnregisterWnd библиотеки d2w.dll.

Функция DriverProc обрабатывает все необходимые сообщения, реагируя на них соответствующим образом. Мы не будем повторять комментарии, приведенные в исходном тексте.Отметим только, что при установке загружаемого драйвера обработчик сообщения DRV_INSTALL дописывает имя приложения wast.exe в строке "load=" файла win.ini, обеспечивая автоматический запуск приложения wast.exe. Для этого он вызывает функцию AutoStartWAST с параметром TRUE.

При удалении драйвера обработчик сообщения отменяет автоматический запуск wast.exe, вызывая функцию AutoStartWAST с параметром FALSE. Перед этим выполняется отмена регистрации. В добавок приложению wast.exe посылается пользовательское сообщение WM_UNLOADWAST. Получив это сообщение, приложение wast.exe завершает свою работу.

Пользовательские сообщения для приложения wast.exe и для загружаемого драйвера, идентификатор виртуального драйвера, а также константа ID_ENABLE определены в файле wastdrv.hpp (листинг 5.13).


Содержание раздела