65.9K
CodeProject is changing. Read more.
Home

Copy an entire registry key with one simple function

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.15/5 (11 votes)

Jan 31, 2001

viewsIcon

134031

A simple API like function that will do this job for you.

Introduction

This small function will copy an entire registry key including all it's values and sub-keys to a new key.

For example, if you wish to copy: HKEY_CURRENT_USER\SoftWare\MySoftware to HKEY_CURRENT_USER\SoftWare\$MYTEMP$, you'll need to do the following:

HKEY SrcKey;
HKEY TrgKey;

RegOpenKeyEx(HKEY_CURRENT_USER,"SoftWare\\MySoftware", 
                                 0, KEY_READ, &SrcKey);
RegOpenKeyEx(HKEY_CURRENT_USER,"SoftWare", 
                                 0, KEY_READ, &TrgKey);

if (RegCopyKey(SrcKey, TrgKey, "$MYTEMP$") == 
                                        ERROR_SUCCESS)
; // All went okay
else
; // Something went wrong

The code

//------------------------------------------------
//  free buffer
//------------------------------------------------
__forceinline void FreeBuff(unsigned char** Buff)
{
    if (*Buff) {
        free(*Buff);
        *Buff = NULL;
    }
}

//-------------------------------------------------
//  allocate buffer
//-------------------------------------------------
__forceinline void AllocBuff(unsigned char** Buff, 
                                    DWORD BuffSize)
{
    FreeBuff(Buff);
    *Buff = (unsigned char*)malloc(BuffSize);
}

//--------------------------------------------------
//  copy key to new position
//--------------------------------------------------
LONG RegCopyKey(HKEY SrcKey, HKEY TrgKey, 
                           char* TrgSubKeyName)
{

    HKEY    SrcSubKey;
    HKEY    TrgSubKey;
    int    ValEnumIndx=0;
    int    KeyEnumIndx=0;
    char    ValName[MAX_PATH+1];
    char    KeyName[MAX_PATH+1];
    DWORD    size;    
    DWORD    VarType;
    DWORD    BuffSize;
    unsigned char*    Buff=NULL;
    LONG    Err;
    DWORD    KeyDisposition;
    FILETIME LastWriteTime; 

    // create target key
    if (RegCreateKeyEx(TrgKey,TrgSubKeyName,
             NULL,NULL,
             REG_OPTION_NON_VOLATILE,
             KEY_ALL_ACCESS,NULL,&TrgSubKey,
             &KeyDisposition) != ERROR_SUCCESS)
        return GetLastError();

    do {
        do {
            // read value from source key
            Err = ERROR_NOT_ENOUGH_MEMORY;
            BuffSize = 1024;
            do {                         
                AllocBuff(&Buff,BuffSize);
                size=MAX_PATH+1;
                Err = RegEnumValue(SrcKey,ValEnumIndx,
                          ValName,&size,NULL,&VarType,
                          Buff,&BuffSize);
                if ((Err != ERROR_SUCCESS) && 
                         (Err != ERROR_NO_MORE_ITEMS))
                    Err = GetLastError();
            } while (Err == ERROR_NOT_ENOUGH_MEMORY);

            // done copying this key
            if (Err == ERROR_NO_MORE_ITEMS)
                break;

            // unknown error return
            if (Err != ERROR_SUCCESS)
                goto quit_err;

            // write value to target key
            if (RegSetValueEx(TrgSubKey,ValName,
                       NULL,VarType,Buff,
                       BuffSize) != ERROR_SUCCESS)
                goto quit_get_err;

            // read next value
            ValEnumIndx++;
        } while (true);

        // free buffer
        FreeBuff(&Buff);

        // if copying under the same 
        // key avoid endless recursions
        do {
            // enum sub keys
            size=MAX_PATH+1;
            Err = RegEnumKeyEx(SrcKey,KeyEnumIndx++,
                            KeyName,&size,NULL,NULL,
                            NULL,&LastWriteTime);
        } while ((SrcKey == TrgKey) && 
           !strnicmp(KeyName,TrgSubKeyName,strlen(KeyName)) && 
           (Err == ERROR_SUCCESS));

        // done copying this key        
        if (Err == ERROR_NO_MORE_ITEMS)
            break;

        // unknown error return
        if (Err != ERROR_SUCCESS)
            goto quit_get_err;

        // open the source subkey
        if (RegOpenKeyEx(SrcKey,KeyName,NULL,
                   KEY_ALL_ACCESS,
                   &SrcSubKey) != ERROR_SUCCESS)
            goto quit_get_err;

        // recurs with the subkey
        if ((Err = CopyKey(SrcSubKey, TrgSubKey, 
                        KeyName)) != ERROR_SUCCESS)
            break;

        if (RegCloseKey(SrcSubKey) != ERROR_SUCCESS)
            goto quit_get_err;
    } while (true);

// normal quit
quit_err:
    FreeBuff(&Buff);
    RegCloseKey(TrgSubKey);
    if (Err == ERROR_NO_MORE_ITEMS)
        return ERROR_SUCCESS;    
    else
        return Err;

// abnormal quit
quit_get_err:
    FreeBuff(&Buff);
    RegCloseKey(TrgSubKey);
    return GetLastError();
}