Материал: Методические указания к практическим занятиям по дисциплине «Основы построения защищенных компьютерных сетей». Деревянко В.Н

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

{

*pIFace = NULL;

return E_NOINTERFACE;

}

((IUnknown*)(*pIFace))->AddRef(); return S_OK;

}

З. Реализация методов пользовательских интерфейсов

Закончив с IUnknown, переходим к реализации пользовательских интерфейсов CоСаr. Добавьте в закрытый сектор следующие данные и инициализируйте их в конструкторе. Используйте корректные функции системных строк при работе с типом bstr:

// Закрытые (Private) данные класса СоСаr

BSTR m_petName; //Инициализация через SysAllocString(); // удаление — вызовом SysFreeString()

int

m_maxSpeed;

// Максимальная скорость объекта СоСаr

int

m_currSpeed;

// Текущая скорость СоСаr

// Конструктор и деструктор СоСаr

СоСаr::СоСаr() : m_refCount(0), m_currSpeed(0), m_maxSpeed(0)

{

m_petName = SysAllocString(L"Default Pet Name");

}

 

CoCar::~CoCar()

 

{

 

if (m_petName)

SysFreeString(m_petName);

}

 

Реализация IEngine проста. Speedup() увеличивает значение m_currspeed на 10 и возвращает S_OK. GetMaxSpeed()

позволяет получить значение переменной m_maxSpeed, a

GetCurrSpeed() — значение m_currSpeed:

// Реализация IEngine STDMETHODIMP CoCar::Speedup()

29

{

m_currSpeed += 10; return S_OK;

}

STDMETHODIMP CoCar::GetMaxSpeed(int* maxSpeed)

{

*maxSpeed = m_maxSpeed; return S_OK;

}

STDMETHODIMP CoCar::GetCurSpeed(int* curSpeed)

{

*curSpeed = m_currSpeed; return S_OK;

}

Интерфейс ICreateCar имеет два метода. SetPetName() принимает заданную клиентом bstr и помещает ее во внутренний буфер bstr, используя

SysReAllocstring(). SetMaxspeed() делает то же, что и раньше: устанавливает максимальную скорость, следя при этом, чтобы она не превышала константу max_speed (которую вы должны задать в заголовочном файле кокласса):

// Реализация ICreateCar

STDMETHODIMP CoCar::SetPetName(BSTR petName)

{

SysReAllocString(&m_petName, petName); return S_OK;

}

STDMETHODIMP CoCar::SetMaxSpeed(int maxSp)

{

if (maxSp < MAX_SPEED) m_maxSpeed = maxSp; return S_OK;

}

И, наконец, остается IStats. GetPetName() возвращает копию внутреннего буфера клиенту. Для этих целей сто-

ит использовать SysAllocString():

// Возвращает клиенту копию внутреннего буфера BSTR STDMETHODIMP CoCar::GetPetName(BSTR* petName)

30

{

*petName = SysAllocString(m_petName); return S_OK;

}

Метод DisplayStats() просто предоставляет два блока сообщений для отображения текущей скорости и имени машины. Единственная заслуживающая внимания деталь в нем

— преобразование Unicode в ANSI:

// Информация о СоСаr идёт в блоки сообщений

STDMETHODIMP CoCar::DisplayStats()

{

// Преобразовать BSTR в массив символов

char buff[MAX_LENGTH]; //Программная константа WideCharToMultiByte(CP_ACP, NULL, m_petName, -1, buff, MAX_LENGTH,

NULL, NULL);

MessageBox(NULL, buff, "Pet Name", MB_OK | MB_SETFOREGROUND); memset(buff, 0, sizeof(buff));

sprintf(buff, "%d", m_maxSpeed);

MessageBox(NULL, buff, "Max Speed", MB_OK| MB_SETFOREGROUND); return S_OK;

}

4.Создание функции начальной загрузки

Вреальной модели СОМ-объекты создаются с помощью библиотечных вызовов. Стандартный интерфейс COM

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

Итак, создадим специальную функцию кoторая знает, как cделать CoCar, и возвращает ссылку на IUnknown. Поместите эту глобальную функцию, именуемую CarFactory(), в

файл СoСаrАрр.срр:

//CarFactory() — глобальная функция, а не часть СоСаr.

//Если присоединим этот метод к СоСаr, то

//мы должны будем создать машину, чтобы создать машину...

31

HRESULT CarFactory(void** pIFace)

{

HRESULT hr;

LPUNKNOWN pUnk = NULL; // typedef для IUnknown

//Динамически отводим память под новый объект СоСаr

СоСаr *pCar = new СоСаr();

//Получаем указатель IUnknown из СоСаr

hr = pCar->QueryInterface(IID_IUnknown, (void**)&pUnk); if(SUCCEEDED(hr))

{

*pIFace = pUnk; return S_OK;

}

else

{

delete pCar; return E_FAIL;

}

}

Теперь динамически можем создавать любое количество объектов СоСаr. Остается написать код клиента.

5. Разработка кода стороны клиента

Нужно добавить код в функцию main () для выполнения следующих операций.

1. С помощью вызова CarFactory() создать объект СоСаr. Для этого необходимо определить переменную IUnknown*, чтобы передать ее в функцию.

// Получаем IUnknown из нового объекта СоСаr

IUnknown* pUnk; HRESULT hr;

hr = CarFactory((void**) SpUnk);

2. Из полученного указателя IUnknown пытаемся получить IID_ICreateCar. Если это проходит успешно, выполняем

32

методы интерфейса:

//Создаем СоСаr ICreateCar *pICreateCar;

pUnk->QUeryInterface(IID_ICreateCar, (void**)&pICreateCar); pICreateCar -> SetMaxSpeed(30);

BSTR name = SysAllocString(OLESTR("Bertha")); pICreateCar -> SetPetName (name); SysFreeString(name);

3.Получаем интерфейс IStats от CoCar и вызываем

DisplayStats().

4.Теперь запрашиваем IEngine. Учитывая логику IUnknown, вы имеете право запросить IEngine из любого допустимого указателя, следовательно, можно вызвать

QueryInterface() из указателей IUnknown или ICreateCar. Используйте IStats::GetPetName() для получения имени кокласса, которое мы можем преобразовать в строку ANSI с помощью WideCharToMultiByte() или wcstombs(), чтобы проинформировать пользователя о выходе за допустимые пределы параметров.

//Ускорение!

int curSp = 0; int maxSp = 0;

pUnk->QueryInterface(IID_IEngine, (void**)&pIEngine); pIEngine -> GetMaxSpeed(&maxSp);

do

{

pIEngine -> SpeedUp();

pIEngine -> GetCurSpeed(&curSp); cout << "Speed is: " << curSp << endl;

} while(curSp <= maxSp);

// Преобразуем в масссив char char buff[MAX_NAME_LENGTH]; BSTR bstr;

pStats -> GetPetName(&bstr);

33

Источник: https://studfile.net/preview/16565401/