Сообщений 0    Оценка 275        Оценить  
Система Orphus

Как скопировать ключ в реестре?

Автор: Александр Шаргин
Опубликовано: 18.02.2001
Исправлено: 13.03.2005
Версия текста: 1.0

Для копирования ключей в реестре предназначена функция SHCopyKey (объявлена в shlwapi.h). Она имеет следующий прототип.

DWORD SHCopyKey(
    HKEY hkeySrc,
    LPCTSTR szSrcSubKey,
    HKEY hkeyDest,
    DWORD fReserved
);

В качестве первого параметра функция получает дескриптор исходного ключа, второй параметр содержит имя подключа, подлежащего копированию, третий - дескриптор целевого ключа, а четвёртый параметр зарезервирован и должен быть равен NULL. Рассмотрим пример копирования ключа "Some key" из раздела HKEY_LOCAL_MACHINE в раздел HKEY_CURRENT_USER.

#include <shlwapi.h>
#pragma comment(lib,"shlwapi.lib")

...

SHCopyKey(HKEY_LOCAL_MACHINE, "Some key", HKEY_CURRENT_USER, NULL);

К сожалению, функция SHCopyKey имеет два серьёзных недостатка. Во-первых, она входит в библиотеку shlwapi.dll только начиная с версии 5.0, а значит, эта функция доступна только под Windows 2000 или при наличии Internet Explorer версии 5.0 и выше. Во-вторых, при копировании ключа ему нельзя задать другое имя. Это исключает применение функции SHCopyKey для переименования ключей в реестре.

Для решения указанных проблем придётся писать собственную функцию, выполняющую копирование ключей. Алгоритм её работы может быть таким: открываем исходный ключ, строим список всех его подключей, рекурсивно вызываем для каждого подключа функцию копирования, а затем строим список всех параметров, содержащихся в ключе, и копируем каждый из них на новое место.

Вот одна из возможных реализаций этого алгоритма.

LONG CopyKey(HKEY hSrcParent, HKEY hTargParent, LPCTSTR szSrcKey, LPCTSTR szTargKey)
{
    LONG nRes;
    TCHAR *szSubKeyName = NULL;
    TCHAR *szValueName = NULL;
    BYTE *pData = NULL;
    HKEY hSrcKey = NULL, hTargKey = NULL;
    
    __try
    {
        nRes = RegCreateKey(hTargParent, szTargKey, &hTargKey);
        if(nRes != ERROR_SUCCESS)
            __leave;

        nRes = RegOpenKeyEx(hSrcParent, szSrcKey, 0, KEY_ENUMERATE_SUB_KEYS | KEY_READ, &hSrcKey);
        if(nRes != ERROR_SUCCESS)
            __leave;

        DWORD nMaxKeyNameLen, nMaxValueNameLen, nMaxValueLen;
        RegQueryInfoKey(
            hSrcKey, NULL, NULL, NULL, NULL,
            &nMaxKeyNameLen, NULL, NULL,
            &nMaxValueNameLen, &nMaxValueLen, NULL, NULL);

        nMaxKeyNameLen++;
        nMaxValueNameLen++;

        szSubKeyName = new TCHAR[nMaxKeyNameLen];
        DWORD nIndex = 0, nSize = nMaxKeyNameLen;
        FILETIME tTime;

        while(RegEnumKeyEx(
            hSrcKey, nIndex++, szSubKeyName, &nSize, 0, NULL, NULL, &tTime) == ERROR_SUCCESS)
        {
            LONG nRes = CopyKey(hSrcKey, hTargKey, szSubKeyName, szSubKeyName);
            if(nRes != ERROR_SUCCESS)
                __leave;

            nSize = nMaxKeyNameLen;
        }

        szValueName = new TCHAR[nMaxValueNameLen];
        pData = new BYTE[nMaxValueLen];
        DWORD nType, nDataSize;

        nIndex = 0;
        nSize = nMaxValueNameLen;
        nDataSize = nMaxValueLen;

        while(RegEnumValue(
            hSrcKey, nIndex++, szValueName, &nSize,
            NULL, NULL, pData, &nDataSize) == ERROR_SUCCESS)
        {
            nRes = RegQueryValueEx(hSrcKey, szValueName, NULL, &nType, pData, &nDataSize);
            if(nRes != ERROR_SUCCESS)
                __leave;

            nRes = RegSetValueEx(hTargKey, szValueName, NULL, nType, pData, nDataSize);
            if(nRes != ERROR_SUCCESS)
                __leave;

            nSize = nMaxValueNameLen;
            nDataSize = nMaxValueLen;
        }

        nRes = ERROR_SUCCESS;
    }
    __finally
    {
        if(szSubKeyName != NULL)
            delete [] szSubKeyName;

        if(szValueName != NULL)
            delete [] szValueName;

        if(pData != NULL)
            delete [] pData;

        if(hSrcKey != NULL)
            RegCloseKey(hSrcKey);

        if(hTargKey != NULL)
            RegCloseKey(hTargKey);

        return nRes;
    }
}

Параметры функции CopyKey аналогичны параметрам SHCopyKey. Обратите внимание, что дополнительный параметр szTargKey позволяет изменить имя исходного ключа при копировании. Вот пример копирования ключа "Some key" из раздела HKEY_LOCAL_MACHINE в раздел HKEY_CURRENT_USER с использованием CopyKey.

CopyKey(HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER, "Some key", "Some key");

Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав.
    Сообщений 0    Оценка 275        Оценить