Драйвер клавиатуры, реализующий функции музыкального синтезатора на клавиатуре для Windows NT 5

Архитектура Windows NT 5. Приоритеты выполнения программного кода. Описание формата MIDI-данных. Установка драйвера в системе. Выбор средств разработки программного обеспечения. Обработка запросов драйверной модели WDM. Использование библиотеки DirectKS.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 24.06.2009
Размер файла 498,8 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Каждое устройство имеет свой раздел в реестре. Все эти разделы находятся в HKEY_LOCAL_MACHINE\SYSTEM\CurrentControleSet\Control\Class. Клавиатуре соответствует раздел {4D36E96B-E325-11CE-BFC1-08002BE10318}. У каждого устройства в его разделе есть ключи UpperFilters и LowerFilters. Это ключи типа MultiString. Они содержат имена верхних и нижних драйверов-фильтров данного устройства. Драйверы-фильтры загружаются в систему в том порядке, в каком они записаны в этих ключах.

Для регистрации разрабатывавемого драйвера как фильтра необходимо поместить его имя в последним в ключе UpperFilters.

Для регистрации нового драйвера необходимо создать раздел с именем этого драйвера в системном реестре по адресу HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services. Этот раздел должен содержать следующие ключи:

Type типа двойное слово

Определяет тип подключаемого модуля.

Интересует только значение SERVICE_KERNEL_DRIVER (1).

Start типа двойное слово

Определяет метод загрузки драйвера. Может принимать одно из следующих значений:

SERVICE_BOOT_START (0) - во время начальной загрузки ОС. Данное значение применяется, когда драйвер используется загрузчиком системы;

SERVICE_SYSTEM_START (1) - после начальной загрузки ОС. Применяется для драйверов, которые самостоятельно осуществляют поиск оборудования, но не используются загрузчиком системы (нумераторы).

SERVICE_AUTO_START (2) - автоматическая загрузка с помощью диспетчера управления сервисами (Service Control Manager). Применяется для драйверов, не поддерживающих Plug and Play.

SERVICE_DEMAND_START (3) - загрузка «по требованию» либо диспетчера Plug and Play при обнаружении устройства, либо диспетчера управления сервисами при поступлении от пользователя команды на загрузку.

SERVICE_DISABLED (4) - драйвер не загружается.

ErrorControl типа двойное слово

Определяет уровень контроля ошибок. Может принимать значения:

SERVICE_ERROR_IGNORE (0). В случае сбоя при загрузке драйвера игнорировать его и продолжить работу.

SERVICE_ERROR_NORMAL (1). В случае сбоя при загрузке драйвера продолжить работу, но выдать при этом соответствующее предупреждение.

SERVICE_ERROR_SEVERE (2). В случае сбоя при загрузке драйвера переключиться на последнюю конфигурацию, при которой работа системы происходила без ошибок.

SERVICE_ERROR_CRITICAL (3). Аналогично (2), но в случае повторного сбоя выдать «синий экран».

DisplayName типа строка ASCII

Экранное имя, отображаемое служебными приложениями на экране. Этот параметр не обязателен. При его отсутствии экранным именем считается имя подраздела.

ImagePath типа строка Unicode

Полный путь к файлу с драйвером на диске. Обычно это поле устанавливается в значение %windir%\system32\Drivers\DriverName.sys, где %windir% -- папка, в которую установлена Windows, а DriverName -- имя файла.

Для разрабатываемого драйвера создаётся раздел с именем kbd_filter с переменными ErrorControl (равна 1), Start (равна 3), Type (равна 1). Т.к. не указывается, где расположен исполняемый файл драйвера, этот файл должен быть скопирован в директорию \%SystemRoot%\System32\Drivers.

В разделе фильтров клавиатуры необходимо внести в переменную UpperFilters имя драйвера-фильтра.

После перезагрузки изменения вступят в силу и драйвер-фильтр начнет работу.

Функции установки и удаления драйвера реализованы в модуле installer, который входит в состав управляющего приложения.

3.3 Сборка программного обеспечения

Для сборки разработанного программного обеспечения необходима ОС Windows NT 5, установленная на компьютере звуковая карта Sound Blaster. Все разработанные компоненты разработанного программного обеспечения находятся в папке DriverControl.

Компиляция

Для того, чтобы скомпилировать драйвер, необходим установленный DDK для Windows NT 5. С помощью консольной утилиты build, входящей в состав DDK, необходимо войти в папку DriverControl\driver и ввести команду build. Произойдёт компиляция драйвера. Драйвер kbd_filter.sys окажется в папке DriverControl\driver\objchk_wnet_x86\i386.

Для того, чтобы скомпилировать управляющую программу, необходимо чтобы был установлен пакет разработки Microsoft Visual Studio .Net. Результатом компиляции является файл DriverControl.exe в папке DriverControl/Release.

Сборка проекта

Чтобы собрать проект (драйвер и управляющая программа) необходимо скопировать в любую папку файл DriverControl.exe, создать в этой папке другую папку driver и поместить в неё файл kbd_filter.sys.

Установка программного обеспечения

Для того, чтобы установить разработанное программное обеспечение на компьютере, необходимо запустить приложение DriverControl.exe. На вкладке «Установка драйвера» нажать на кнопку «Установить». Для того, чтобы изменения в системе вступили в силу, необходимо перезагрузить компьютер.

Установленный драйвер можно увидеть с помощью утилиты devicetree, входящей в состав DDK.

3.4 Использование библиотеки DirectKS

Библиотека DirectKS предоставляет функциональность для работы с интерфейсом Kernel Streaming в режиме пользователя. В исходном варианте DirectKS работает с устройствами, поддерживающими формат WAVE-данных. Задачей данной курсовой работы является работа с MIDI-устройствами. Поэтому в библиотеку были внесены изменения. Библиотека находится в файле DriverControl/directks. Все внесённые изменения описаны в Приложении (см пункт 6.2).

Библиотека DirectKS используется следующим образом:

CKsAudRenPin * OpenMidiPin()

{HRESULT hr;

CKsAudRenFilter * pFilter = NULL;

CKsAudRenPin * pPin = NULL;

CKsEnumFilters * pEnumerator = new CKsEnumFilters(&hr);

GUID aguidEnumCats[] = {STATIC_KSCATEGORY_AUDIO};

// Найти все фильтры категории STATIC_KSCATEGORY_AUDIO

// Создаст списки всех пинов этих фильтров

hr = pEnumerator->EnumFilters(eAudRen, aguidEnumCats, 1, TRUE, FALSE, TRUE);

if(SUCCEEDED(hr))

{// Перечислить все фильтры и пины, пока не будет найден

// пин нужного формата данных - формата MIDI

LISTPOS listPos = pEnumerator->m_listFilters.GetHeadPosition();

while(!pPin && pEnumerator->m_listFilters.GetNext(listPos, (CKsFilter**)&pFilter))

{pPin = pFilter->CreateRenderPin(FALSE);}}

delete pFilter;

return pPin;}

Если пин с нужным форматом данных обнаружен, то функция возвращает указатель на класс для работы с пином.

Для того чтобы получить HANDLE пина, нужно использовать свойство:

Pin->GetHandle()

3.5 Отправление запросов из приложения в драйвер

key_midi - модуль отправления запросов из приложения в драйвер, находится в папке driverio.

Этот модуль содержит таблицу соответствий позиции клавиши к паре (скан-код, флаг).

#define KEY_MIDI_FILE "C:\\KeyMidi.dat"

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

HRESULT KeyGetScanCode(OUT PUCHAR ScanCode, OUT PUCHAR Flag,

IN UCHAR Position);

По позиции клавиши определяется её скан-код и флаг.

HRESULT KeySaveNote(IN LPCTSTR FileName, IN UCHAR ScanCode,

IN UCHAR Flag, IN UCHAR Position,

IN UCHAR Channel, IN UCHAR Instrument, IN UCHAR Note,

IN UCHAR Used);

Сохраняет в файле FileName музыкальную информацию о клавише.

HRESULT KeyGetNote(IN LPCTSTR FileName,

OUT PUCHAR ScanCode, OUT PUCHAR Flag, IN UCHAR Position,

OUT PUCHAR Channel, OUT PUCHAR Instrument,

OUT PUCHAR Note);

По позиции клавиши получает из файла FileName её музыкальную информацию.

HRESULT KeyDriverSendNote(IN UCHAR ScanCode, IN UCHAR Flag,

IN UCHAR Position, IN UCHAR Channel,

IN UCHAR Instrument, IN UCHAR Note,

IN UCHAR Used);

Сохраняет в драйвере музыкальную информацию о клавише.

HRESULT KeyDriverSendAllNotes(IN LPCTSTR FileName);

Сохраняет в драйвере музыкальную информацию обо всех клавишах, музыкальная информация о которых сохранена в файле FileName.

HRESULT SharePinWithDriver(IN HANDLE Pin);

Отправляет в драйвер HANDLE открытого пина.

3.6 Описание интерфейса пользователя

Установка

Для того чтобы установить или удалить драйвер необходимо открыть программу DriverControl.exe. Выбрать вкладку «Установка драйвера». Кнопки «Установить» и «Удалить» означают установку или удаление драйвера из системы (рис. 3.1). Для того, чтобы изменения вступали в силу, необходимо перезагружать компьютер.

В случае, если на компьютере не найдены нужные аудиоустройства, будет выведено сообщение «Невозможно открыть MIDI-пин». В этом случае драйвер установить можно будет, но назначить ноты для клавиши будет нельзя.

Рис.3.1. Установка драйвер

Управление

Для того чтобы можно было управлять драйвером, нужно выбрать в программе DrivcrControl.exe вкладку «Назначение звука». Выбирая кнопку, которая соответствует клавиши клавиатуры, можно для неё назначить канал, инструмент и ноту. Можно предварительно проверить звучание ноты, а потом сохранить музыкальную информацию в драйвере. Информация будет продублирована в файле C:\KeyMidi.dat.

Рис.3.2. Управление драйвером

Автозагрузка

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

Для этого было создано простое приложение, которое открывает пин, отправляет его в драйвер, отправляет в драйвер информацию обо всех музыкальных параметрах, созранённых в файле C:\KeyMidi.dat.

Проект этого приложения находится в папке DriverControl под названием DriverAutoloader. Скомпилированную программу DriverAutoloader.exe можно найти в папке DriverControl/Release. Эту программу по желанию можно сохранить в папке Startup, приложения из которой загружаются во время загрузки ОС Windows.

3.7 Тестирование программного обеспечения

Драйвер был протестирован с использованием стандартной тестирующей утилиты DriverVerifier пакета DDK. С его помощью были проведены следующие тесты:

Операции с пулами памяти

Корректность уровней IRQL, на которых выполняется код драйвера

Обнаружение взаимоблокировок

Нехватка ресурсов

Нетипичные запросы к драйверу

Все тесты прошли успешно. Память в системе распределялась правильно, ошибок с ней не возникало. На нехватку ресурсов драйвер реагировал корректно. Нетипичные запросы к драйверу не обрабатывались им.

После установки драйвера и назначения музыкальных параметров для клавиш работа драйвера продолжается без «синего экрана».

На компьютерах, где не установлены звуковые карты Sound Blaster клавиши не издают звуков, т.к. встроенные звуковые карты не поддерживают тех IOCTL-запросов, которые используются во время работы с объектом пина.

Тестирование происходило на ОС Windows XP и Windows Server 2003.

4. Заключение

Исследована структура драйверов Windows

Определено место драйвера в стеке драйверов и выбрана структура программного обеспечения, состоящего из двух частей:

- верхнего драйвера-фильтра клавиатуры

- программы, которая осуществляет настройку параметров музыкального озвучивания клавиш и управляет работой драйвера посредством IOCTL-запросов

Изучены механизмы:

- встраивания драйвера-фильтра в стек драйверов

- взаимодействия компонент программного обеспечения через IOCTL-запросы

Разработаны механизмы:

- поиска доступа к аудиоустройству в режиме ядра

- синхронизации потоков, работающих на разных уровнях IRQL

Разработано программное обеспечение в соответствии с техническим заданием и проведено его тестирование.

Разработанный программный продукт полностью удовлетворяет поставленной задаче и осуществляет настраиваемое озвучивание нажатий клавиш на клавиатуре под управлением ОС Microsoft Windows NT 5.

5. Список литературы

1. Oney W. Programming the Microsoft Windows Driver Model.-- Redmond, Washington: Microsoft Press., 1999.

2. Форум разработчиков MS Windows на сайте microsoft.com.

3. Рассылка, посвящённая разработке аудиодрайверов на сайте wdmaudiodev.de

4. Рассылка, посвящённая разработке драйверов для Windows на сайте osronline.com

5. Microsoft Windows Server 2003 DDK Documentation.

6. Приложения

6.1 Функции установки драйвера в системе

#define DRIVER_KEY "System\\CurrentControlSet\\Services\\"DRIVER_NAME

#define FILTER_KEY "System\\CurrentControlSet\\Control\\Class\\{4D36E96B-E325-11CE-BFC1-08002BE10318}"

char * SearchString(char * Value, DWORD ValueLength, char * String)

{if(ValueLength < strlen(String)) return NULL;

DWORD len = (DWORD) (ValueLength - strlen(String));

do

{if(!stricmp(&Value[len], String) && (!len || !Value[len - 1]))

{return &Value[len];}}

while(len--);

return NULL;}

HRESULT DriverWasInstalled()

{HKEY hKeyFilter;

DWORD type, length;

char filters[MAX_PATH];

HRESULT hr = S_OK;

if(RegCreateKey(HKEY_LOCAL_MACHINE, FILTER_KEY, &hKeyFilter) == ERROR_SUCCESS)

{length = sizeof(filters);

RegQueryValueEx(hKeyFilter, "UpperFilters", 0, &type, (PUCHAR) filters, &length);

if(SearchString(filters, length, DRIVER_NAME))

{hr = S_OK;}

else

{hr = E_FAIL;}

RegCloseKey(hKeyFilter);}

Else

{hr = E_FAIL;}

return hr;}

HRESULT InstallDriver()

{HKEY hKeyDriver, hKeyFilter;

DWORD value, type, length;

char filters[MAX_PATH];

char SystemDirectory[MAX_PATH];

HRESULT hr = S_OK;

GetSystemDirectory(SystemDirectory, sizeof(SystemDirectory));

strcat(SystemDirectory, "\\Drivers\\"DRIVER_NAME".sys");

if(!CopyFile("driver\\"DRIVER_NAME".sys", SystemDirectory, FALSE))

{hr = E_ACCESSDENIED;}

else if(RegCreateKey(HKEY_LOCAL_MACHINE, DRIVER_KEY, &hKeyDriver) == ERROR_SUCCESS &&

RegCreateKey(HKEY_LOCAL_MACHINE, FILTER_KEY, &hKeyFilter) == ERROR_SUCCESS)

{value = 1;

RegSetValueEx(hKeyDriver, "Type", 0, REG_DWORD, (PUCHAR) &value, sizeof(value));

value = 1;

RegSetValueEx(hKeyDriver,"ErrorControl",0,REG_DWORD, (PUCHAR)&value, sizeof(value));

value = 3;

RegSetValueEx(hKeyDriver, "Start", 0, REG_DWORD, (PUCHAR) &value, sizeof(value));

length = sizeof(filters);

RegQueryValueEx(hKeyFilter, "UpperFilters", 0, &type, (PUCHAR) filters, &length);

if(!SearchString(filters, length, DRIVER_NAME))

{strcpy(&filters[length - 1], DRIVER_NAME);

length += (DWORD) strlen(DRIVER_NAME);

filters[length] = 0;

RegSetValueEx(hKeyFilter,"UpperFilters",0,type, (PUCHAR)filters, length+1);}

else

{hr = S_FALSE;}

RegCloseKey(hKeyDriver);

RegCloseKey(hKeyFilter);}

else

{DeleteFile(SystemDirectory);

hr = E_ACCESSDENIED;}

return hr;}

HRESULT UninstallDriver()

{HKEY hKey;

DWORD type, length;

char filters[MAX_PATH], * ptr;

char SystemDirectory[MAX_PATH];

HRESULT hr = S_OK;

if(RegOpenKey(HKEY_LOCAL_MACHINE, FILTER_KEY, &hKey) == ERROR_SUCCESS)

{length = sizeof(filters);

RegQueryValueEx(hKey, "UpperFilters", 0, &type, (PUCHAR) filters, &length);

if(ptr = SearchString(filters, length, DRIVER_NAME))

{memcpy(ptr,ptr+strlen(DRIVER_NAME)+1,length-(ptr-filters)-strlen(DRIVER_NAME)-1);

length -= (DWORD) strlen(DRIVER_NAME) + 1;

RegSetValueEx(hKey, "UpperFilters", 0, type, (PUCHAR) filters, length);}

else

{hr = S_FALSE;}

RegCloseKey(hKey);}

else

{hr = E_ACCESSDENIED;}

RegDeleteKey(HKEY_LOCAL_MACHINE, DRIVER_KEY"\\Security");

RegDeleteKey(HKEY_LOCAL_MACHINE, DRIVER_KEY"\\Enum");

RegDeleteKey(HKEY_LOCAL_MACHINE, DRIVER_KEY);

GetSystemDirectory(SystemDirectory, sizeof(SystemDirectory));

strcat(SystemDirectory, "\\Drivers\\"DRIVER_NAME".sys");

if(!DeleteFile(SystemDirectory))

{hr = S_FALSE;}

return hr;}

6.2 Изменения в библиотеке DirectKS

В файле audfilter.cpp

Что заменить:

CKsAudRenPin*

CKsAudRenFilter::CreateRenderPin

(const WAVEFORMATEX* pwfx,

BOOL fLooped)

{TRACE_ENTER();

HRESULT hr = S_OK;

CKsAudRenPin* pPin = FindViablePin(pwfx);

if (!pPin)

{DebugPrintf(TRACE_NORMAL, TEXT("Could not find a Render pin that supports the given wave format"));

hr = E_FAIL;}

else

{hr = pPin->SetFormat(pwfx);

if (FAILED(hr))

{DebugPrintf(TRACE_ERROR, TEXT("Failed to set Render Pin format - the pin lied about its supported formats"));}}

if (SUCCEEDED(hr))

{hr = pPin->Instantiate(fLooped);

if (SUCCEEDED(hr))

{DebugPrintf(TRACE_LOW, TEXT("Successfully instantiated Render Pin. Handle = 0x%08x"), pPin->GetHandle());}

else

{DebugPrintf(TRACE_ERROR, TEXT("Failed to instantiate Render Pin"));}}

if (FAILED(hr))

{// Initialize pPin to NULL again

pPin = NULL;

// Try to intstantiate all the pins, one at a time

CKsPin *pKsPin;

LISTPOS listPosPin = m_listRenderSinkPins.GetHeadPosition();

while( !pPin && m_listRenderSinkPins.GetNext( listPosPin, &pKsPin ))

{CKsAudRenPin *pKsAudRenPin = (CKsAudRenPin *)pKsPin;

hr = pKsAudRenPin->SetFormat( pwfx );

if (SUCCEEDED(hr))

{hr = pKsAudRenPin->Instantiate(fLooped);}

if (SUCCEEDED(hr))

{// Save the pin in pPin

pPin = pKsAudRenPin;

break;}}}

if (FAILED(hr))

{// Don't delete the pin - it's still in m_listRenderPins

//delete pPin;

pPin = NULL;}

else

{// Remove the pin from the filter's list of pins

LISTPOS listPosPinNode = m_listPins.Find( pPin );

assert(listPosPinNode);

m_listPins.RemoveAt( listPosPinNode );

listPosPinNode = m_listRenderSinkPins.Find( pPin );

assert(listPosPinNode);

m_listRenderSinkPins.RemoveAt( listPosPinNode );}

TRACE_LEAVE_HRESULT(hr);

return pPin;}

Заменить на:

CKsAudRenPin*

CKsAudRenFilter::CreateRenderPin

(BOOL fLooped)

{TRACE_ENTER();

HRESULT hr = S_OK;

CKsAudRenPin * pPin = FindViablePin();

if(!pPin)

{DebugPrintf(TRACE_NORMAL, TEXT("Could not find a Render pin that supports the given wave format"));

hr = E_FAIL;}

if(SUCCEEDED(hr))

{hr = pPin->Instantiate(fLooped);

if (SUCCEEDED(hr))

{DebugPrintf(TRACE_LOW, TEXT("Successfully instantiated Render Pin. Handle = 0x%08x"), pPin->GetHandle());}

else

{DebugPrintf(TRACE_ERROR, TEXT("Failed to instantiate Render Pin"));}}

/*if(FAILED(hr))

{// Initialize pPin to NULL again

pPin = NULL;

// Try to intstantiate all the pins, one at a time

CKsPin * pKsPin;

LISTPOS listPosPin = m_listRenderSinkPins.GetHeadPosition();

while(!pPin && m_listRenderSinkPins.GetNext(listPosPin, &pKsPin))

{CKsAudRenPin * pKsAudRenPin = (CKsAudRenPin *)pKsPin;

hr = pKsAudRenPin->Instantiate(fLooped);

if(SUCCEEDED(hr))

{// Save the pin in pPin

pPin = pKsAudRenPin;

break;}}}*/

if(FAILED(hr))

{// Don't delete the pin - it's still in m_listRenderPins

//delete pPin;

pPin = NULL;}

else

{// Remove the pin from the filter's list of pins

LISTPOS listPosPinNode = m_listPins.Find(pPin);

assert(listPosPinNode);

m_listPins.RemoveAt(listPosPinNode);

listPosPinNode = m_listRenderSinkPins.Find(pPin);

assert(listPosPinNode);

m_listRenderSinkPins.RemoveAt(listPosPinNode);}

TRACE_LEAVE_HRESULT(hr);

return pPin;}

Что заменить:

CKsAudRenPin*

CKsAudRenFilter::FindViablePin

(const WAVEFORMATEX* pwfx)

{TRACE_ENTER();

assert( pwfx );

CKsPin* pNode;

LISTPOS listPos = m_listRenderSinkPins.GetHeadPosition();

while(m_listRenderSinkPins.GetNext( listPos, &pNode ))

{CKsAudRenPin* pPin = (CKsAudRenPin*)pNode;

// To only look at non-digital output pins, check that pPin->IsVolumeSupported() is TRUE,

// as digital output pins don't have volume controls associated with them.

if( pPin->IsFormatSupported( pwfx ) )

{// This should be a valid pin

TRACE_LEAVE();

return pPin;}}

TRACE_LEAVE();

return NULL;}

Заменить на:

CKsAudRenPin*

CKsAudRenFilter::FindViablePin

(){TRACE_ENTER();

CKsPin * pNode;

LISTPOS listPos = m_listRenderSinkPins.GetHeadPosition();

while(m_listRenderSinkPins.GetNext( listPos, &pNode ))

{CKsAudRenPin * pPin = (CKsAudRenPin*)pNode;

// To only look at non-digital output pins, check that pPin->IsVolumeSupported() is TRUE,

// as digital output pins don't have volume controls associated with them.

if(pPin->IsFormatSupported())

{/ This should be a valid pin

TRACE_LEAVE();

return pPin;}}

TRACE_LEAVE();

return NULL;}

В файле audfilter.h

Что заменить:

CKsAudRenPin* CreateRenderPin(const WAVEFORMATEX* pwfx, BOOL fLooped);

Заменить на:

CKsAudRenPin * CreateRenderPin(BOOL fLooped);

Что заменить:

CKsAudRenPin* FindViablePin(const WAVEFORMATEX* pwfx);

Заменить на:

CKsAudRenPin * FindViablePin();

В файле audpin.cpp

Что заменить:

BOOL CKsAudPin::IsFormatSupported(const WAVEFORMATEX* pwfx)

{TRACE_ENTER();

LISTPOS listPosRange = m_listDataRange.GetHeadPosition();

KSDATARANGE_AUDIO* pKSDATARANGE_AUDIO;

while( m_listDataRange.GetNext( listPosRange, &pKSDATARANGE_AUDIO ) )

{if( KSDATAFORMAT_TYPE_WILDCARD == pKSDATARANGE_AUDIO->DataRange.MajorFormat

|| KSDATAFORMAT_TYPE_AUDIO == pKSDATARANGE_AUDIO->DataRange.MajorFormat )

{// Set the format to search for

GUID guidFormat = {DEFINE_WAVEFORMATEX_GUID(pwfx->wFormatTag)};

// If this is a WaveFormatExtensible structure, then use its defined SubFormat

if( WAVE_FORMAT_EXTENSIBLE == pwfx->wFormatTag )

{guidFormat = ((WAVEFORMATEXTENSIBLE *)pwfx)->SubFormat;}

if( KSDATAFORMAT_SUBTYPE_WILDCARD == pKSDATARANGE_AUDIO->DataRange.SubFormat

|| guidFormat == pKSDATARANGE_AUDIO->DataRange.SubFormat )

{if( KSDATAFORMAT_SPECIFIER_WILDCARD == pKSDATARANGE_AUDIO->DataRange.Specifier

|| KSDATAFORMAT_SPECIFIER_WAVEFORMATEX == pKSDATARANGE_AUDIO->DataRange.Specifier )

{if( pKSDATARANGE_AUDIO->MaximumChannels >= pwfx->nChannels

&& pKSDATARANGE_AUDIO->MinimumBitsPerSample <= pwfx->wBitsPerSample

&& pKSDATARANGE_AUDIO->MaximumBitsPerSample >= pwfx->wBitsPerSample

&& pKSDATARANGE_AUDIO->MinimumSampleFrequency <= pwfx->nSamplesPerSec

&& pKSDATARANGE_AUDIO->MaximumSampleFrequency >= pwfx->nSamplesPerSec )

{// This should be a valid pin

TRACE_LEAVE();

return TRUE;}}}}}

TRACE_LEAVE();

return FALSE;}

Заменить на:

BOOL CKsAudPin::IsFormatSupported()

{TRACE_ENTER();

LISTPOS listPosRange = m_listDataRange.GetHeadPosition();

KSDATARANGE_MUSIC * pKSDATARANGE_MUSIC;

while(m_listDataRange.GetNext(listPosRange, &pKSDATARANGE_MUSIC))

{if(KSDATAFORMAT_TYPE_WILDCARD == pKSDATARANGE_MUSIC->DataRange.MajorFormat

||KSDATAFORMAT_TYPE_MUSIC == pKSDATARANGE_MUSIC->DataRange.MajorFormat)

{if(KSDATAFORMAT_SUBTYPE_WILDCARD == pKSDATARANGE_MUSIC->DataRange.SubFormat

||KSDATAFORMAT_SUBTYPE_MIDI == pKSDATARANGE_MUSIC->DataRange.SubFormat)

{if(KSDATAFORMAT_SPECIFIER_WILDCARD == pKSDATARANGE_MUSIC->DataRange.Specifier

||KSDATAFORMAT_SPECIFIER_NONE == pKSDATARANGE_MUSIC->DataRange.Specifier)

{if(KSMUSIC_TECHNOLOGY_SWSYNTH == pKSDATARANGE_MUSIC->Technology)

{// This should be a valid pin

TRACE_LEAVE();

return TRUE;}}}}}

TRACE_LEAVE();

return FALSE;}

Что заменить:

HRESULT CKsAudPin::Init()

{TRACE_ENTER();

HRESULT hr = S_OK;

BOOL fViablePin = FALSE;

// Make sure at least one interface is standard streaming

if (SUCCEEDED(hr))

{fViablePin = FALSE;

for(ULONG i = 0; i < m_Descriptor.cInterfaces && !fViablePin; i++)

{fViablePin =

fViablePin ||

IsEqualGUIDAligned(m_Descriptor.pInterfaces[i].Set, KSINTERFACESETID_Standard) &&

(m_Descriptor.pInterfaces[i].Id == KSINTERFACE_STANDARD_STREAMING) ;}

if (!fViablePin)

{DebugPrintf(TRACE_ERROR, TEXT("No standard streaming interfaces on the pin"));

hr = E_FAIL;}}

// Make sure at least one medium is standard streaming

if (SUCCEEDED(hr))

{fViablePin = FALSE;

for(ULONG i = 0; i < m_Descriptor.cInterfaces && !fViablePin; i++)

{fViablePin =

fViablePin ||

IsEqualGUIDAligned(m_Descriptor.pMediums[i].Set, KSMEDIUMSETID_Standard) &&

(m_Descriptor.pMediums[i].Id == KSMEDIUM_STANDARD_DEVIO) ;}

if (!fViablePin)

{DebugPrintf(TRACE_ERROR, TEXT("No standard streaming mediums on the pin"));

hr = E_FAIL;}}

// Make sure at least one datarange supports audio

if (SUCCEEDED(hr))

{fViablePin = FALSE;

PKSDATARANGE pDataRange = m_Descriptor.pDataRanges;

for(ULONG i = 0; i < m_Descriptor.cDataRanges; i++)

{// SubType should either be compatible with WAVEFORMATEX or

// it should be WILDCARD

fViablePin =

fViablePin ||

IS_VALID_WAVEFORMATEX_GUID(&pDataRange->SubFormat) ||

IsEqualGUIDAligned(pDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_PCM) ||

IsEqualGUIDAligned(pDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD);

if (fViablePin && IsEqualGUIDAligned(pDataRange->MajorFormat, KSDATAFORMAT_TYPE_AUDIO))

{// Copy the data range into the pin

PKSDATARANGE_AUDIO pCopyDataRangeAudio = new KSDATARANGE_AUDIO;

if( pCopyDataRangeAudio )

{PKSDATARANGE_AUDIO pDataRangeAudio = (PKSDATARANGE_AUDIO)pDataRange;

CopyMemory( pCopyDataRangeAudio, pDataRangeAudio, sizeof(KSDATARANGE_AUDIO) );

if (NULL == m_listDataRange.AddTail( pCopyDataRangeAudio ))

{delete pCopyDataRangeAudio;

pCopyDataRangeAudio = NULL;

DebugPrintf(TRACE_ERROR, TEXT("Unable to allocate list entry to save datarange in"));

hr = E_OUTOFMEMORY;}}

else

{DebugPrintf(TRACE_ERROR, TEXT("Unable to allocate memory to save datarange in"));

hr = E_OUTOFMEMORY;}}

pDataRange = (PKSDATARANGE)( ((PBYTE)pDataRange) + pDataRange->FormatSize);}

if (!fViablePin)

{DebugPrintf(TRACE_ERROR, TEXT("No audio dataranges on the pin"));

hr = E_FAIL;}}

TRACE_LEAVE_HRESULT(hr);

return hr;}

Заменить на:

HRESULT CKsAudPin::Init()

{TRACE_ENTER();

HRESULT hr = S_OK;

BOOL fViablePin = FALSE;

// Make sure at least one interface is standard streaming

if (SUCCEEDED(hr))

{fViablePin = FALSE;

for(ULONG i = 0; i < m_Descriptor.cInterfaces && !fViablePin; i++)

{fViablePin =

fViablePin ||

IsEqualGUIDAligned(m_Descriptor.pInterfaces[i].Set, KSINTERFACESETID_Standard) &&

(m_Descriptor.pInterfaces[i].Id == KSINTERFACE_STANDARD_STREAMING) ;}

if (!fViablePin)

{DebugPrintf(TRACE_ERROR, TEXT("No standard streaming interfaces on the pin"));

hr = E_FAIL;}}

// Make sure at least one medium is standard streaming

if (SUCCEEDED(hr))

{fViablePin = FALSE;

for(ULONG i = 0; i < m_Descriptor.cInterfaces && !fViablePin; i++)

{fViablePin =

fViablePin ||

IsEqualGUIDAligned(m_Descriptor.pMediums[i].Set, KSMEDIUMSETID_Standard) &&

(m_Descriptor.pMediums[i].Id == KSMEDIUM_STANDARD_DEVIO) ;}

if (!fViablePin)

{DebugPrintf(TRACE_ERROR, TEXT("No standard streaming mediums on the pin"));

hr = E_FAIL;}}

// Make sure at least one datarange supports audio

if (SUCCEEDED(hr))

{fViablePin = FALSE;

PKSDATARANGE pDataRange = m_Descriptor.pDataRanges;

for(ULONG i = 0; i < m_Descriptor.cDataRanges; i++)

{fViablePin = fViablePin ||

IsEqualGUIDAligned(pDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_MIDI) ||

IsEqualGUIDAligned(pDataRange->SubFormat, KSDATAFORMAT_SUBTYPE_WILDCARD);

if (fViablePin && IsEqualGUIDAligned(pDataRange->MajorFormat, KSDATAFORMAT_TYPE_MUSIC))

{// Copy the data range into the pin

PKSDATARANGE_MUSIC pCopyDataRangeAudio = new KSDATARANGE_MUSIC;

if( pCopyDataRangeAudio )

{PKSDATARANGE_MUSIC pDataRangeAudio = (PKSDATARANGE_MUSIC)pDataRange;

CopyMemory( pCopyDataRangeAudio, pDataRangeAudio, sizeof(KSDATARANGE_MUSIC) );

if (NULL == m_listDataRange.AddTail( pCopyDataRangeAudio ))

{delete pCopyDataRangeAudio;

pCopyDataRangeAudio = NULL;

DebugPrintf(TRACE_ERROR, TEXT("Unable to allocate list entry to save datarange in"));

hr = E_OUTOFMEMORY;}}

else

{DebugPrintf(TRACE_ERROR, TEXT("Unable to allocate memory to save datarange in"));

hr = E_OUTOFMEMORY;}}

pDataRange = (PKSDATARANGE)( ((PBYTE)pDataRange) + pDataRange->FormatSize);}

if (!fViablePin)

{DebugPrintf(TRACE_ERROR, TEXT("No audio dataranges on the pin"));

hr = E_FAIL;}}

TRACE_LEAVE_HRESULT(hr);

return hr;}

Что заменить:

CKsAudPin::~CKsAudPin(void)

{TRACE_ENTER();

KSDATARANGE_AUDIO *pKSDATARANGE_AUDIO;

CKsNode *pKsNode;

// Clear datarange list

while( m_listDataRange.RemoveHead(&pKSDATARANGE_AUDIO) )

{delete pKSDATARANGE_AUDIO;}

// Clear the node list

while( m_listNodes.RemoveHead(&pKsNode) )

{delete pKsNode;}

delete[] (BYTE *)m_pWaveFormatEx;

TRACE_LEAVE();

return;}

Заменить на:

CKsAudPin::~CKsAudPin(void)

{TRACE_ENTER();

KSDATARANGE_MUSIC * pKSDATARANGE_MUSIC;

CKsNode * pKsNode;

// Clear datarange list

while(m_listDataRange.RemoveHead(&pKSDATARANGE_MUSIC))

{delete pKSDATARANGE_MUSIC;}

// Clear the node list

while(m_listNodes.RemoveHead(&pKsNode))

{delete pKsNode;}

TRACE_LEAVE();

return;}

Что заменить:

CKsAudPin::CKsAudPin

(CKsAudFilter* pFilter,

ULONG nId,

HRESULT* phr

) : CKsPin(pFilter, nId, phr),

m_pAudFilter(pFilter),

m_pWaveFormatEx(NULL),

m_pksDataFormatWfx(NULL)

{TRACE_ENTER();

HRESULT hr = *phr;

if (SUCCEEDED(hr))

{hr = m_listDataRange.Initialize(1);

if (FAILED(hr))

DebugPrintf(TRACE_ERROR,TEXT("Failed to Initialize m_listDataRange"));}

if (SUCCEEDED(hr))

{hr = m_listNodes.Initialize(1);

if (FAILED(hr))

DebugPrintf(TRACE_ERROR,TEXT("Failed to Initialize m_listNodes"));}

// create a KSPIN_CONNECT structure to describe a waveformatex pin

if (SUCCEEDED(hr))

{m_cbPinCreateSize = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX);

m_pksPinCreate = (PKSPIN_CONNECT)new BYTE[m_cbPinCreateSize];

if (!m_pksPinCreate)

{DebugPrintf(TRACE_ERROR,TEXT("Failed to allocate m_pksPinCreate"));

hr = E_OUTOFMEMORY;}}

if (SUCCEEDED(hr))

{m_pksPinCreate->Interface.Set = KSINTERFACESETID_Standard;

m_pksPinCreate->Interface.Id = KSINTERFACE_STANDARD_STREAMING;

m_pksPinCreate->Interface.Flags = 0;

m_pksPinCreate->Medium.Set = KSMEDIUMSETID_Standard;

m_pksPinCreate->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE;

m_pksPinCreate->Medium.Flags = 0;

m_pksPinCreate->PinId = nId;

m_pksPinCreate->PinToHandle = NULL;

m_pksPinCreate->Priority.PriorityClass = KSPRIORITY_NORMAL;

m_pksPinCreate->Priority.PrioritySubClass = 1;

// point m_pksDataFormatWfx to just after the pConnect struct

PKSDATAFORMAT_WAVEFORMATEX pksDataFormatWfx = (PKSDATAFORMAT_WAVEFORMATEX)(m_pksPinCreate + 1);

// set up format for KSDATAFORMAT_WAVEFORMATEX

pksDataFormatWfx->DataFormat.FormatSize = sizeof(KSDATAFORMAT_WAVEFORMATEX);

pksDataFormatWfx->DataFormat.Flags = 0;

pksDataFormatWfx->DataFormat.Reserved = 0;

pksDataFormatWfx->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;

pksDataFormatWfx->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;

pksDataFormatWfx->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;

m_pksDataFormatWfx = pksDataFormatWfx;}

// Initialize the Pin;

if (SUCCEEDED(hr))

{hr = CKsAudPin::Init();}

TRACE_LEAVE_HRESULT(hr);

*phr = hr;

return;}

Заменить на:

CKsAudPin::CKsAudPin

(CKsAudFilter* pFilter,

ULONG nId,

HRESULT* phr

) : CKsPin(pFilter, nId, phr),

m_pAudFilter(pFilter),

m_pksDataFormat(NULL)

{TRACE_ENTER();

HRESULT hr = *phr;

if (SUCCEEDED(hr))

{hr = m_listDataRange.Initialize(1);

if (FAILED(hr))

DebugPrintf(TRACE_ERROR,TEXT("Failed to Initialize m_listDataRange"));}

if (SUCCEEDED(hr))

{hr = m_listNodes.Initialize(1);

if (FAILED(hr))

DebugPrintf(TRACE_ERROR,TEXT("Failed to Initialize m_listNodes"));}

// create a KSPIN_CONNECT structure to describe a waveformatex pin

if (SUCCEEDED(hr))

{m_cbPinCreateSize = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT);

m_pksPinCreate = (PKSPIN_CONNECT)new BYTE[m_cbPinCreateSize];

if (!m_pksPinCreate)

{DebugPrintf(TRACE_ERROR,TEXT("Failed to allocate m_pksPinCreate"));

hr = E_OUTOFMEMORY;}}

if (SUCCEEDED(hr))

{m_pksPinCreate->Interface.Set = KSINTERFACESETID_Standard;

m_pksPinCreate->Interface.Id = KSINTERFACE_STANDARD_STREAMING;

m_pksPinCreate->Interface.Flags = 0;

m_pksPinCreate->Medium.Set = KSMEDIUMSETID_Standard;

m_pksPinCreate->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE;

m_pksPinCreate->Medium.Flags = 0;

m_pksPinCreate->PinId = nId;

m_pksPinCreate->PinToHandle = NULL;

m_pksPinCreate->Priority.PriorityClass = KSPRIORITY_NORMAL;

m_pksPinCreate->Priority.PrioritySubClass = 1;

// point m_pksDataFormat to just after the pConnect struct

PKSDATAFORMAT pksDataFormat = (PKSDATAFORMAT)(m_pksPinCreate + 1);

// set up format for KSDATAFORMAT

pksDataFormat->FormatSize = sizeof(KSDATAFORMAT);

pksDataFormat->Flags = 0;

pksDataFormat->SampleSize = 0;

pksDataFormat->Reserved = 0;

pksDataFormat->MajorFormat = KSDATAFORMAT_TYPE_MUSIC;

pksDataFormat->SubFormat = KSDATAFORMAT_SUBTYPE_MIDI;

pksDataFormat->Specifier = KSDATAFORMAT_SPECIFIER_NONE;

m_pksDataFormat = pksDataFormat;}

// Initialize the Pin;

if (SUCCEEDED(hr))

{hr = CKsAudPin::Init();}

TRACE_LEAVE_HRESULT(hr);

*phr = hr;

return;}

В файле audpin.h

Что заменить:

TList<KSDATARANGE_AUDIO> m_listDataRange;

Заменить на:

TList<KSDATARANGE_MUSIC> m_listDataRange;

Что заменить:

BOOL IsFormatSupported(const WAVEFORMATEX* pwfx);

Заменить на:

BOOL IsFormatSupported();

Что заменить:

KSDATAFORMAT_WAVEFORMATEX* m_pksDataFormatWfx;

Заменить на:

KSDATAFORMAT * m_pksDataFormat;


Подобные документы

  • Архитектура ввода/вывода Windows NT. Внутренняя организация шины USB. Сущностная характеристика драйверной модели WDM. Точки входа разрабатываемого драйвера, размещение кода в памяти, установка драйвера в системе. Реализация кода драйвера на языке C.

    курсовая работа [1,2 M], добавлен 27.09.2014

  • Разработка и практическая апробация действия драйвер-фильтра клавиатуры для операционной системы Windows, переопределяющего значение любых клавиш и отключающего клавиши клавиатуры. Составление программы для установки и управления данным драйвером.

    курсовая работа [226,8 K], добавлен 18.06.2009

  • Разработка программного обеспечения для упрощения буквенно-цифрового ввода при невозможности использовать функционал стандартной буквенной клавиатуры. Классификация и установка драйверов. Выбор языка и среды программирования. Пользовательский интерфейс.

    курсовая работа [183,0 K], добавлен 12.03.2013

  • Описание принципа работы драйвера. Установка и регистрация драйвера. Назначение и возможности утилиты TestTerminals.exe. Использование редактора форм. Создание форм с помощью редактора задач. Последовательность выполнения операций и обработок данных.

    курсовая работа [843,6 K], добавлен 09.11.2011

  • Методика исследования и анализа средств аудита системы Windows с целью обнаружения несанкционированного доступа программного обеспечения к ресурсам вычислительных машин. Анализ угрозы информационной безопасности. Алгоритм работы программного средства.

    дипломная работа [2,9 M], добавлен 28.06.2011

  • Управление задачами и процессами, запускаемыми под управлением Microsoft Windows. Учетные записи пользователей Windows. Установка оборудования и программного обеспечения. Изменение параметров и удаление учетной записи. Проверка дисков на наличие ошибок.

    реферат [2,7 M], добавлен 23.05.2012

  • Основные характеристики графики в операционной системе Windows, реализация объектно-ориентированной идеологии. Специфика и этапы разработки программного продукта, описывающего графический объект, на 32-битном ассемблере с использованием API-функции.

    курсовая работа [82,3 K], добавлен 18.05.2014

  • Общий календарный план выполнения этапов проекта программного обеспечения. Последовательность разработки согласно классической каскадной модели. Изображение хода работ по спиральной модели согласно Боему. Технические требования на продукт, WBS-структура.

    лабораторная работа [614,1 K], добавлен 17.01.2014

  • Многослойная архитектура драйверов. Организация внутреннего хранения данных диска. Выбор и обоснование языка и среды программирования. Обработка расширенных запросов. Процедуры установки драйвера виртуального диска. Блокировка выгрузки устройства.

    курсовая работа [159,1 K], добавлен 23.06.2009

  • Классификация служебных программных средств. Файловая структура операционных систем. Основы графического интерфейса пользователя Windows XX. Анализ алгоритмов решения задач. Описание процесса разработки программного обеспечения и результатов работы.

    курсовая работа [2,4 M], добавлен 14.11.2016

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.