Ir al contenido


Foto

Mover claves del registro recursivamente [MULTILENGUAJE]


  • Por favor identifícate para responder
2 respuestas en este tema

#1 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 12 abril 2018 - 01:30

Con fines de esconder claves o realizar un BackUp de una clave guardándola dentro del registro, pensé en escribir un código para copiar una clave, sus valores y sus subclaves, en otra zona del registro de Windows.
 
Aparentemente no debería ser complicado copiar claves del registro arrastrando todos sus valores y subclaves, para eso M$ dispone de las API RegCopyTree y SHCopyKey. El problema es que estas API tienen restricciones de copia. No quedando contento con las pruebas que realicé y para generalizar la solución al problema he escrito una función recursiva que copia una clave a otro lugar.
 
Primero crea la subclave de destino, luego enumera y copia los valores, y finalmente, copia las subclaves, En este último punto la función se vuelve recursiva para repetir las acciones fasta la última rama del árbol.
 

delphi
  1. function RegCopyKey(SrcKey, TrgKey: HKEY; TrgSubKeyName: PAnsiChar): integer;
  2. var
  3. SrcSubKey: HKEY;
  4. TrgSubKey: HKEY;
  5. ValIndex: integer;
  6. KeyIndex: integer;
  7.  
  8. ValName: array [0..MAX_PATH] of AnsiChar;
  9. KeyName: array [0..MAX_PATH] of AnsiChar;
  10. Size: DWORD;
  11. ValType: DWORD;
  12. BuffSize: DWORD;
  13. Buff: PBYTE;
  14. begin
  15. ValIndex:= 0;
  16. KeyIndex:= 0;
  17.  
  18. Result:= 2;
  19. if (SrcKey = 0) or (TrgKey = 0) then exit;
  20.  
  21. // Creando La Clave Destino
  22. Result:= RegCreateKeyExA(TrgKey, TrgSubKeyName, 0, nil, REG_OPTION_NON_VOLATILE,
  23. KEY_ALL_ACCESS, nil, TrgSubKey, nil);
  24. if Result = ERROR_SUCCESS then
  25. begin
  26. Size:= sizeof(ValName);
  27.  
  28. // Copio valores
  29. while ERROR_NO_MORE_ITEMS <> RegEnumValueA(SrcKey, ValIndex, ValName, Size, nil, @ValType, nil, @BuffSize) do
  30. begin
  31. Buff:= VirtualAlloc(nil, BuffSize, MEM_COMMIT, PAGE_READWRITE);
  32. RegEnumValueA(SrcKey, ValIndex, ValName, Size, nil, @ValType, Buff, @BuffSize);
  33. RegSetValueExA(TrgSubKey, ValName, 0, ValType, Buff, BuffSize);
  34. VirtualFree(Buff, 0, MEM_RELEASE);
  35. Size:= sizeof(ValName);
  36. inc(ValIndex);
  37. end;
  38. // Copio Claves recursivamente
  39. Size:= sizeof(KeyName);
  40. while ERROR_NO_MORE_ITEMS <> RegEnumKeyEx(SrcKey, KeyIndex, KeyName, Size, nil, nil, nil, nil) do
  41. begin
  42. if RegOpenKeyExA(SrcKey, KeyName, 0, KEY_ALL_ACCESS, SrcSubKey) = ERROR_SUCCESS then
  43. begin
  44. if 0 = lstrcmpi(@KeyName[0], @TrgSubKeyName[0]) then continue;
  45. if ERROR_SUCCESS <> RegCopyKey(SrcSubKey, TrgSubKey, KeyName) then break;
  46. RegCloseKey(SrcSubKey);
  47. end;
  48. Size:= sizeof(KeyName);
  49. inc(KeyIndex);
  50. end;
  51.  
  52. RegCloseKey(TrgSubKey);
  53. end;
  54. end;

Un ejemplo de uso que copia HKEY_CLASSES_ROOT\batfile\shell en  HKEY_CLASSES_ROOT\batfile\bkShell

delphi
  1. var
  2. SrcKey, TrgKey: HKEY;
  3. begin
  4. RegOpenKeyEx(HKEY_CLASSES_ROOT, 'batfile\shell', 0, KEY_READ, SrcKey);
  5. RegOpenKeyEx(HKEY_CLASSES_ROOT, 'batfile', 0, KEY_READ, TrgKey);
  6. RegCopyKey(SrcKey, TrgKey, 'bkShell');
  7. RegCloseKey(SrcKey);
  8. RegCloseKey(TrgKey);
  9. end;

Añadiendo el borrado de la clave original, tenemos el código listo para mover claves:

delphi
  1. type
  2.  
  3. function RegDeleteTree(KeyScr: HKEY; lpSubKey: LPCTSTR): integer; stdcall; external 'Advapi32.dll' name 'RegDeleteTreeA';
  4.  
  5.  
  6. ..................
  7.  
  8. var
  9. SrcKey, TrgKey: HKEY;
  10. begin
  11. RegOpenKeyEx(HKEY_CLASSES_ROOT, 'batfile\shell\runas', 0, KEY_READ, SrcKey);
  12. RegOpenKeyEx(HKEY_CLASSES_ROOT, 'batfile', 0, KEY_READ, TrgKey);
  13. RegCopyKey(SrcKey, TrgKey, 'bkRunAs');
  14. RegCloseKey(SrcKey);
  15. RegCloseKey(TrgKey);
  16. RegDeleteTree(HKEY_CLASSES_ROOT, 'batfile\shell\runas');
  17. end;

Saludos.

PD/ Edito para unificar en AnsiChar
  • 0

#2 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 12 abril 2018 - 01:33

Como no podía ser de otra manera, publico el código en C/C++

cpp
  1. LONG RegCopyKey(HKEY SrcKey, HKEY TrgKey, char* TrgSubKeyName)
  2. {
  3. HKEY SrcSubKey;
  4. HKEY TrgSubKey;
  5. int ValIndex = 0;
  6. int KeyIndex = 0;
  7. char ValName[MAX_PATH+1];
  8. char KeyName[MAX_PATH+1];
  9. DWORD Size;
  10. DWORD ValType;
  11. DWORD BuffSize;
  12. PBYTE Buff;
  13. LONG Error;
  14.  
  15. if(SrcKey == 0 || TrgKey == 0) return 2;
  16.  
  17. // Creo Clave destino
  18. Error = RegCreateKeyExA(TrgKey, TrgSubKeyName, NULL, NULL, REG_OPTION_NON_VOLATILE,
  19. KEY_ALL_ACCESS, NULL, &TrgSubKey, 0);
  20.  
  21. if(Error == ERROR_SUCCESS){
  22. // Copio valores
  23. Size = sizeof(ValName);
  24. while(ERROR_NO_MORE_ITEMS != RegEnumValueA(SrcKey, ValIndex, ValName, &Size, NULL, &ValType, NULL, &BuffSize)){
  25. Size = sizeof(ValName);
  26. Buff = (PBYTE)VirtualAlloc(0, BuffSize, MEM_COMMIT, PAGE_READWRITE);
  27. RegEnumValueA(SrcKey, ValIndex++, ValName, &Size, NULL, &ValType, Buff, &BuffSize);
  28. RegSetValueExA(TrgSubKey, ValName, NULL, ValType, Buff, BuffSize);
  29. VirtualFree(Buff, 0, MEM_RELEASE);
  30. }
  31. // Copio Claves recursivamente
  32. Size = sizeof(KeyName);
  33. while(ERROR_NO_MORE_ITEMS != RegEnumKeyEx(SrcKey, KeyIndex++, KeyName, &Size, 0, 0, 0, 0)){
  34. Size = sizeof(KeyName);
  35. if(RegOpenKeyExA(SrcKey, KeyName, NULL, KEY_ALL_ACCESS, &SrcSubKey) == ERROR_SUCCESS){
  36. if(!strnicmp(KeyName, TrgSubKeyName, strlen(KeyName))) continue;
  37. if(ERROR_SUCCESS != RegCopyKey(SrcSubKey, TrgSubKey, KeyName)) break;
  38. RegCloseKey(SrcSubKey);
  39. }
  40. }
  41.  
  42. RegCloseKey(TrgSubKey);
  43. }
  44. return Error;
  45. }

Dado que el código es similar al escrito en delphi, los ejemplos de uso también lo son.
 
 
Saludos.

PD/ Edito para unificar en AnsiChar
  • 1

#3 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 12 abril 2018 - 02:08


Muy interesante solución amigo escafandra, sobre todo para gente como yo que gustamos de borrar llaves del registro :D :D :D

Saludos
  • 0




IP.Board spam blocked by CleanTalk.