Сущность технологии СОМ. Библиотека программиста | страница 91



, szFileName, MAXPATH);

// register entries from table

// регистрируем записи из таблицы

int nEntries = sizeof(gRegTable)/sizeof(*gRegTable);

for (int i = 0; SUCCEEDED(hr) && i < nEntries; i++)

{

const char *pszKeyName = gRegTable[i][0];

const char *pszValueName = gRegTable[i][1];

const char *pszvalue = gRegTable[i][2];

// map rogue value to module file name

// переводим нестандарное значение в имя файла модуля

if (pszValue == (const char*)-1) pszValue = szFileName;

HKEY hkey;

// create the key

// создаем ключ

long err = RegCreateKeyA(HKEYCLASSESROOT, pszKeyName, &hkey);

if (err == ERRORSUCCESS)

{

// set the value

// присваиваем значение

err = RegSetValueExA(hkey, pszVvalueName, 0, REGSZ, (const BYTE*) pszValue, (strlen(pszValue) + 1));

RegCloseKey(hkey);

}

if (err != ERRORSUCCESS)

{

// if cannot add key or value, back out and fail

// если невозможно добавить ключ или значение, то откат и сбой

DllUnregisterServer();

hr = SELFREGECLASS;

}

}

return hr;

}


Соответствующая DllUnregisterServer будет выглядеть так:


STDAPI DllUnregisterServer(void)

{

HRESULT hr = SOK;

int nEntries = sizeof(gRegTable)/sizeof(*gRegTable);

for (int i = nEntries – 1; i >= 0; i-)

{

const char *pszKeyName = gRegTable[i][0];

long err = RegDeleteKeyA(HKEYCLASSESROOT, pszKeyName);

if (err != ERRORSUCCESS) hr = SFALSE; }

return hr;

}


Отметим, что реализация DllUnregisterServer просматривает таблицу с конца, начиная с последней входной точки. Делается это для преодоления ограничения RegDeleteKey, в котором разрешаются только такие ключи, у которых нет подключей, подлежащих удалению. Реализация DllUnregisterServer требует такой организации таблицы, чтобы все подключи каждого ключа появлялись в таблице после входа родительского ключа.

Так как СОМ преобразует CLSID в данный файл реализации, то для объявления в СОМ относящихся к серверу объектов класса необходимо использовать определенные стандартные методики. Для сервера, основанного на исполняемой программе, в СОМ предусмотрены явные API-функции для связывания объектов класса с их CLSID . Эти API-функции мы будем подробно обсуждать в главе 6. Для сервера, основанного на DLL, DLL должна экспортировать известную функцию, которая будет вызываться с помощью CoGetClassObject, когда потребуется объект класса. Эту функцию необходимо экспортировать с использованием файла определения модулей, причем она должна иметь следующий вид:


HRESULT DllGetClassObject(

[in] REFCLSID rclsid,

// which class object?