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

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

Домашнее задание №2 для подготовки к занятиям по разработке сетевого приложения для Windows на С++

Цель задания Подготовиться к занятиям по разработке сетевого при-

ложения для Windows на языке С++. Изучить применение методов интерфейса IUnknown.

Для освоения работы с GUID, HRESULT, счетчиком ссылок, строками СОМ и логику IUnknown разработаем программу CoCarApp.exe. Она пока не является стандартным СОМ клиент/серверным приложением: объект СОМ создается и исполняется внутри одиночного исполняемого файла.

Кокласс CоСаr, построенный здесь, будет использоваться на следующем занятии, где мы поместим класс СОМ в исполняемый "домик" DLL, который затем будет доступен для СОМ-клиента.

Пример проекта данной работы содержится в каталоге

… \Ch3\CoCarApp3-1.

1. Проектирование интерфейса

Для проекта консольного приложения Win32, выберите Empty application. Разработаем класс, поддерживающий три пользовательских интерфейса. В предыдущем домашнем заданиия класс CCаr предоставлял все функциональные возможности автомобиля через единственный открытый интерфейс. Этот интерфейс можно разбить на логические группы (интерфейсы). Создадим новый заголовочный файл с именем interfaces.h и определим три новых интерфейса, которые моделируют поведение автомобиля:

/* IStats используется для получения имени автомобиля,а также для отображения параметров состояния реализуемого объекта */ DECLARE_INTERFACE_(IStats,IUnknown)

24

{

STDMETHOD(DisplayStats)() PURE; STDMETHOD(GetPetName)(BSTR* petName) PURE;

};

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

DECLARE_INTERFACE_(IEngine, IUnknown)

{

STDMETHOD(SpeedUp)() PURE; STDMETHOD(GetMaxSpeed)(int* maxSpeed) PURE; STDMETHOD(GetCurSpeed)(int* curSpeed) PURE;

};

/* ICreateCar используется для присвоения имени реализуемому объекту и задания максимальной скорости */

DECLARE_INTERFACE_(ICreateCar, IUnknown)

{

STDMETHOD(SetPetName)(BSTR petName) PURE; STDMETHOD(SetMaxSpeed)(int maxSp) PURE;

};

Все пользовательские интерфейсы СОМ должны быть произведены от IUnknown, так что не забудьте добавить

#include <windows.h> в файл. interfaces.h. Также добавьте к определению интерфейса директивы препроцессора

#ifndef /#define/ #endif, чтобы предотвратить ошиб-

ки повторного определения.

Присвойте GUID каждому пользовательскому интерфейсу. Создайте другой заголовочный файл с именем iid.h, который будет содержать описания макросов define_guid. Используя guidgen.exe, создайте три новых GUID с соответствующими константами (с префиксом IID_). Вот примеры GUID для каждого интерфейса (у вас будут, конечно же, другие):

// {A533DA30-D372-11d2-B8CF-0020781238D4}

25

DEFINE_GUID(IID_IEngine,

Oxa533da30, Oxd372, Ox11d2, Oxb8, Oxcf, 0x0, 0x20, 0x78, 0x12, 0x38, Oxd4);

//{A533DA31-D372-11d2-B8CF-0020781238D4} DEFINE_GUID(IID_IStats,

. . .

//{A533fiA32-D372-11d2-B8CF-0020781238D4} DEFINE_GUID(IID_ICreateCar,

. . .

Создайте еще один новый файл с именем iid.cpp. Он должен содержать только следующие ниже #include. He забудьте вставить его в рабочее пространство проекта (исполь-

зуйте меню Project | Add To Project | Files).

#include <windows.h>

// Для всего, относящегося к СОМ

#include <initguid.h>

// Для DEFINE_GUID

#include "iid.h"

// IID

Иметь один централизованный файл для всех GUID ваших приложений очень полезно, если вам потребуется включать определения в другие проекты. Полезно иметь и соответствующий файл *.срр для ID ваших интерфейсов.

2. Реализация IUnknown

Вставьте новый класс C++ с именем СоCаr, содержащий интерфейсы IEngine, IStats и ICreateCar. Понадобит-

ся реализовать не только методы каждого пользовательского интерфейса, но и три метода IUnknown. Вот начальный заголовочный файл для СоCаr:

// СоСаr реализует четыре интерфейса СОМ

#include "interfaces.h"

class CoCar : public IEngine, public ICreateCar, public IStats

{

public:

CoCar();

virtual ~CoCar(); // IUnknown

26

STDMETHODIMP QueryInterface(REFIID riid, void** pIFace); STDMETHODIMP_(ULONG)AddRef(); STDMETHODIMP_(ULONG)Release();

// IEngine

STDMETHODIMP SpeedUp();

STDMETHODIMP GetMaxSpeed(int* maxSpeed); STDMETHODIMP GetCurSpeed(int* curSpeed); // IStats

STDMETHODIMP DisplayStats(); STDMETHODIMP GetPetName(BSTR* petName); // ICreateCar

STDMETHODIMP SetPetName(BSTR petName); STDMETHODIMP SetMaxSpeed(int maxSp) ;

};

Мы не будем использовать cout в реализации методов интерфейсов Car. На этот раз возьмем функцию MessageBox() Win32 API. Это позволит нам перенести класс СоСаr в исполняемую DLL в следующей работе, не привязываясь к консольному клиенту Win32.

Сначала реализуем счетчик ссылок. Добавьте закрытый (private) счетчик ссылок с именем m_refcount (типа ULONG) к классу СоСаr и обнулите его в конструкторе. Функция AddRef() будет добавлять к счетчику единицы, a Release() — отнимать единицы и проверять на окончательный сброс, после которого объект сам себя выгрузит из памяти с помощью команды delete this.

// Схема счетчика ссылок объекта

STDMETHODIMP_(ULONG) CoCar::AddRef()

{

return ++m_refCount;

}

STDMETHODIMP_(ULONG) CoCar::Release()

{

if (--m_refCount == 0)

27

{

delete this; return 0;

}

else

return m_refCount;

}

Теперь реализуем Queryinterface(), чтобы возвращать указатели интерфейса для IUnknown, IStats, ICreateCar и IEngine. He забудьте вызвать AddRef(),

если вы предоставляете указатель интерфейса, и вернуть e_nointerface в случае отсутствия поддержки интерфейса:

//QueryInterfасе() отвечает за видимость

//указателя "this" для данного клиента

STDMETHODIMP CoCar::QueryInterface(REFIID riid, void** pIFace)

{

// Что конкретно от меня хотят? if(riid == IID_IUnknown)

{

*pIFace = (IUnknown*) (IEngine*)this;

}

else if (riid == IID_IEngine)

{

*pIFace = (IEngine*)this;

}

else if (riid = IID_IStats)

{

*pIFace = (IStats*) this;

}

else if (rud == IID_ICreateCar)

{

*pIFace = (ICreateCar*)this;

}

else

28

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