Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
198
Добавлен:
20.02.2016
Размер:
45.06 Кб
Скачать

Лабораторная работа №2

Создание диалоговой прикладной программы для управления драйверами.

Интерфейс:

Программа должна предоставлять диалоговое окно с четырьмя полями ввода и 7 кнопками

Приблизительно окно должно выглядеть так:

Назначение полей ввода

  • Задание имени сервиса ServiceName (с этим именем в реестре будет создан ключ HKEY_LOCAL_MASHINE\System\CurrentControlSet\Services\ServiceName, описывающий местоположение драйвера, способ его загрузки и т.п.)

  • Задание имени символической ссылки на имя устройства. В это поле должно быть введено имя, определенное загружаемым нами драйвером при создании устройства

  • Задание полного пути к sys-файлу с драйвером. Это имя будет помещено в реестр как значение ключа HKEY_LOCAL_MASHINE\System\CurrentControlSet\Services\ServiceName\ImagePath

  • Поле для вывода журнала работы программы (отображение результатов работы функций программы, коды и описания ошибок)

Назначение кнопок:

  • Вывод окна запроса пути к sys-файлу

  • Добавление драйвера в систему

  • Удаление драйвера из системы

  • Запуск драйвера

  • Остановка драйвера

  • Открытие устройства

  • Закрытие устройства

Создание проекта:

  • Запустить Visual C++

  • Выбрать пункт меню File\New…

  • В появившемся окне выбрать тип проекта – “MFC AppWizard (exe)”, в поле Location задать путь к своей рабочей директории, в поле Project Name – имя проекта (instdrv). Нажать Ok

  • В появившемся окне мастера создания приложений MFC выбрать тип приложения “Dialog Based”. Жать кнопку Next, пока она доступна. После этого – Finish. Будет создан проект на базе диалогового окна.

  • Ресурс с диалоговым окном находится в диспетчере проектов в закладке ResourceView в пункте Dialog\IDD_INSTDRV_DIALOG (второе диалоговое окно, IDD_ABOUTBOX, мы использовать не будем). В закладке ClassView находится список классов C++ нашего приложения – по одному классу на каждое диалоговое окно и класс для всего приложения. В закладке FileView находится список всех файлов проекта. Оба класса блоков диалога помещены в один cpp-файл, класс приложения – в другой cpp-файл. Каждый cpp-файл имеет одноименный ему h-файл.

  • Вставить в блок диалога все элементы управления. Для этого перейти к закладке ResourceView, выбрать нужный блок диалога. Появится окно редактирования ресурса и панель с элементами управления (Controls). В этой панели выбрать поля ввода (Edit Box) и кнопки (Button). Для вставки пояснений к полям ввода добавить элементы управления Static Text.

  • Для изменения заголовков элементов управления щелкнуть на элементе управления в диалоговом окне правой кнопкой мыши, в появившемся меню – пункт Properties. В появившемся окне поменять поле Caption (надпись на элементе управления) и поле ID (идентификатор ресурса). В качестве идентификаторов ресурсов выбирать осмысленные имена, типа IDADD для кнопок или IDC_PATH для полей ввода.

  • Отдельное внимание уделить полю ввода для вывода журнала работы программы. В его свойствах перейти в закладку Styles, выбрать пункт Multiline, все пункты во втором столбике (Horizontal Scroll и т.д.), и пункт WantReturn в третьем столбике свойств.

  • Создать в классе диалогового окна поля-члены класса, соответствующие всем полям ввода текста в блоке диалога. Для этого в блоке диалога щелкнуть правой кнопкой мыши на нужном поле ввода, в появившемся меню выбрать ClassWizard. В появившемся окне перейти в закладку Member Variables, выбрать кнопку Add Variable… В появившемся окне в поле Category задать Control, в поле Variable Type – Cedit, в поле Member Variable Name задать имя переменной, например m_edtPath (префикс m_ означает, что это член класса, edt указывает на то, что переменная имеет тип CEdit).

  • В интегрированной подсказке изучить класс MFC CEdit. Нас будут интересовать функции-члены класса GetWindowText(), SetWindowText(),ReplaceSel().

  • Нас также будет интересовать класс CString, который можно использовать везде, где требуются нуль-терминированные строки.

  • Исследовать класс CFileDialog, предоставляющий блок диалогового окна открытия файла. Нас будет интересовать его конструктор, функция-член DoModal() и ее возвращаемое значение и функция-член GetPathName().

  • Создать функции – обработчики событий нажатия на кнопки. Для этого вызвать ClassWizard, в закладке MessageMaps выбрать идентификатор ресурса нужной кнопки, в списке Messages выбрать BN_CLICKED и нажать кнопку AddFunction. После запроса имени функции обработчик будет добавлен и в него можно будет перейти или из окна ClassWizard нажатием на кнопку EditCode, или из закладки ClassView диспетчера проектов выбором соответствующей функции-члене в классе CInstdrvDlg.

  • Создать новый класс CScMgr, который будет заниматься работой с ServiceControlManager’ом посредством вызова функций Win32 OpenSCManager(), CreateService(), CloseServiceHandle(), OpenService(),DeleteService(), StartService(),ControlService() и использовать функции CreateFile() и CloseHandle() для открытия и закрытия устройства. Изучить эти функции в помощи. Пример использования этих функций можно посмотреть на E:\DDK\Src\General\InstDrv\exe\instdrv.c. Для создания класса перейти в закладку ClassView диспетчера проектов, выбрать верхнюю строку (Instdrv classes), щелкнуть на ней правой кнопкой мыши, в появившемся меню выбрать “New Class”. В качестве типа класса указать “Generic Class”.

  • Конструктор класса должен инициализировать переменную-член класса, представляющую описатель ServiceControlManager’а, с помощью функции OpenSCManager(). Деструктор класса должен освобождать описатель с помощью вызова CloseServiceHandle(). Должны быть реализованы функции-члены класса, реализующие установку, удаление, запуск и остановку драйвера, открытие и закрытие устройства. В случае возникновения ошибок информация о них должна быть выведена в поле журнала работы программы. Для этого обратить внимание на функции GetLastError() и FormatMessage().

  • Функции – обработчики событий нажатия на кнопки должны содержать вызов соответствующих функций класса CScMgr. Экземпляр класса создается и уничтожается внутри функции-обработчике события.

Далее приводится пример реализации функции вывода сообщения в формате функции vprintf() в поле ввода с именем m_edtDump, и функции получения и вывода сообщения об ошибке в то же поле.

void CInstdrvDlg::vspf(char *fmt, va_list argptr)

{

memset(tmpbuf, 0, sizeof(tmpbuf));

vsprintf(tmpbuf, fmt, argptr);

strcat(tmpbuf, "\r\n");

m_edtDump.ReplaceSel(tmpbuf);

}

void CInstdrvDlg::PrintLastError(char *fmt, va_list argptr)

{

LPVOID lpMsgBuf;

int cnt;

memset(tmpbuf, 0, sizeof(tmpbuf));

FormatMessage(

FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,

NULL,

GetLastError(),

MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language

(LPTSTR) &lpMsgBuf,

0,

NULL

);

cnt = vsprintf(tmpbuf, fmt, argptr);

strcat(tmpbuf, (char*)lpMsgBuf);

strcat(tmpbuf, "\r\n");

m_edtDump.ReplaceSel(tmpbuf);

// Free the buffer.

LocalFree( lpMsgBuf );

}

В классе работы с ServiceControlManager’ом должны быть соответствующие функции vspf и PrintLastError, принимающие переменное число параметров

в формате функции printf, например:

int CScMgr::vspf(char *fmt, ...)

{

va_list argptr;

va_start(argptr, fmt);

((CInstdrvDlg*)(theApp.m_pMainWnd))->vspf(fmt, argptr);

va_end(argptr);

}

Смысл этой функции в том, чтобы из функции-члена одного класса (CScMgr) вызвать функцию-член другого класса (CInstdrvDlg). Сделать это можно через переменную – указатель на экземпляр класса CInstdrvDlg. Проблема в том, что эта переменная в свою очередь является членом третьего класса – CInstdrvApp, и вдобавок имеет тип указателя на базовый для CInstdrvDlg класс – CDialog. Переменная – указатель на экземпляр класса CInstdrvApp является глобальной переменной.

Упрощенная схема этих классов выглядит следующим образом:

class CInstdrvApp

{

CDialog *m_pMainWnd; //инициализация этой переменной происходит

//в функции CInstdrvApp::InitInstance()

};

CInstdrvApp theApp; //глобальная переменная

class CInstdrvDlg: public CDialog

{

...

void vspf(char *fmt, va_list argptr);

void PrintLastError(char *fmt, va_list argptr);

...

//переменные, соответствующие полям редактирования (CEdit)

...

//функции-обработчики событий нажатия на кнопки

...

};

class CScMgr

{

...

void vspf(char *fmt, ...);

void PrintLastError(char *fmt, ...);

...

//функции установки, удаления, запуска и остановки драйвера

//и открытия устройства

...

};

4

Соседние файлы в папке Лабы по драйверам