Сущность технологии СОМ. Библиотека программиста | страница 91
// 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?