Manipulando o registro do Windows - C/C++

Started by Dark_Side, 19 de December , 2006, 04:14:30 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Dark_Side

Hi,

Dias atrás, escrevi um texto abordando a manipulação do registro do Windows através do Delphi. Seguindo a dica de uma pessoa que estava tendo dificuldades em trabalhar com o registro em C/C++, decidi escrever este artigo abordando como fazê-lo.

Se você ir até o Menu Iniciar -> Executar; digitar "regedit.exe" e pressionar OK, irá se deparar com um programa denominado Editor de Registro.

Veja:



O editor de registro é basicamente representado pela figura acima.
Temos as chaves principais:

QuoteHKEY_CLASSES_ROOT
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
HKEY_CURRENT_CONFIG

À direita, temos todos os valores, tipos e dados de uma chave ou subchave.
Como você pode observar, as chaves principais são como pastas comuns. Podemos fazer a seguinte analogia:

QuoteChaves do registro - pastas de arquivos;
Valores - nome dos arquivos dentro destas pastas;
Tipo - tipo de cada arquivo;
Dados - conteúdo de cada arquivo.

Assim como as pastas Windows, System e System32, o registro armazena valores vitais do sistema, que, se por algum motivo forem deletados, pode-se comprometer o funcionamento parcial ou total do sistema. Por esta razão, é necessário um cuidado especial ao manipular as informações contidas no registro, assim como faríamos com arquivos contidos nas pastas do sistema listadas acima.

Vejamos agora como trabalhar com o registro em C/C++.

O primeiro passo para se trabalhar com o registro é incluir todos os headers necessários para tal:

#include <windows.h>
int main()
{

return 0;
}

Acima, inclui-se o header "windows.h". Na verdade, o header por si próprio, não contém as funções e constantes destinadas à manipulação do registro. Estas estão contidas no header "winreg.h", contudo, incluindo "windows.h" estamos também incluindo-o.

Podemos continuar =)

1) Criando um chave

Se analisarmos bem, o correto seria "Criando uma subchave" pois iremos SEMPRE criar uma chave dentro de outra - seja esta última uma chave raiz ou uma outra criada por nós. Mas isso não é tão importante.

Veja:

#include <windows.h>

int main()
{
HKEY chave;

if(RegCreateKey(HKEY_CURRENT_USER,"Minha Chave",&chave) != 0)
 {
   MessageBox(0,"Ocorreu um erro ao criar a chave!","Erro",0x10);
   return 1;}

RegCloseKey(chave);   
         
      return 0;
}

No código acima, temos um exemplo de como criar uma chave dentro de  "HKEY_CURRENT_USER".

Observando o código, notamos que há uma váriavel do tipo HKEY - chave.
Variáveis do tipo HKEY armazenam valores relacionados a chaves do registro.

Veja o trecho responsável por tentar criar a chave "Minha Chave":

if(RegCreateKey(HKEY_CURRENT_USER,"Minha Chave",&chave) != 0)
 {
   MessageBox(0,"Ocorreu um erro ao criar a chave!","Erro",0x10);
   return 1;}
 

A sintaxe é:

QuoteLONG WINAPI RegCreateKey(HKEY chave, LPCWSTR nome_chave,PHKEY ponteiro_hkey);
 
   chave:
      valor da chave na qual criaremos uma subchave; pode ser uma chave raiz;

   nome_chave:
      seria o nome (string) da subchave a ser criada;

   ponteiro_hkey:
      ponteiro para uma variável do tipo HKEY que irá armazenar o valor da chave criada.

A função retorna ZERO caso a chave tenha sido criada corretamente, ou um valor DIFERENTE DE ZERO, caso contrário.

No código, tentamos criar a chave 'Minha Chave' e armazenar o seu valor na variável 'chave'. Se algum erro ocorrer, é exibida uma alerta e o programa encerra.

Sempre depois que terminamos de trabalhar com uma chave do registro, devemos fechá-la:

RegCloseKey(chave);   

A sintaxe é:
QuoteRegCloseKey(valor_chave);

   valor_chave:
        valor da chave a ser fechada; geralmente armazenado por uma variável do tipo HKEY.


Pode criar diversas subchaves, veja:

#include <windows.h>

int main()
{
HKEY chave;

if(RegCreateKey(HKEY_CURRENT_USER,"Minha Chave\\Sub1\\Sub2\\Sub3",&chave) != 0)
 {
   MessageBox(0,"Ocorreu um erro ao criar a chave!","Erro",0x10);
   return 1;}

RegCloseKey(chave);   
         
      return 0;
}

As seguintes subchaves seriam criadas: Minha Chave\Sub1\Sub2\Sub3.

Algo importante a ser observado é que, em C/C++, a barra "" é representada por "\"

Outro detalhe, é que criando subchaves da maneira acima, a variável "chave" conterá o valor da última subchave, no caso "Sub3".


2) Abrindo uma chave existente

Quando queremos apenar abrir uma chave, fazemos:

#include <windows.h>

int main()
{
HKEY chave;

if(RegOpenKey(HKEY_CURRENT_USER,"Minha Chave",&chave) != 0)
 {
   MessageBox(0,"Ocorreu um erro ao abrir a chave!","Erro",0x10);
   return 1;}

RegCloseKey(chave);   
         
      return 0;
}

Caso a chave 'Minha Chave' exista em HKEY_CURRENT_USER, esta seria aberta e seu valor seria armazenado na variável chave.

A sintaxe da função é:

QuoteLONG WINAPI RegOpenKey(HKEY chave, LPCWSTR nome_chave,PHKEY ponteiro_hkey);
 
   chave:
      valor da chave na qual a subchave que iremos abrir está contida; pode ser uma chave raiz;

   nome_chave:
      seria o nome (string) da subchave a ser aberta;

   ponteiro_hkey:
      ponteiro para uma variável do tipo HKEY que irá armazenar o valor da chave aberta.

A função retorna ZERO caso a chave tenha sido aberta corretamente, ou um valor DIFERENTE DE ZERO, caso contrário.

Uma observação a ser feita é quando criamos uma chave, não é necessária abri-la com a função RegOpenKey. Veja o porque:

RegCreateKey(HKEY_CURRENT_USER,"Minha Chave",&chave);
Acima, se a chave "Minha Chave" for criada, a variável "chave" irá armazenar o seu valor, ou seja, já estará associada a essa chave criada.



3) Criando um valor

Para criamos um valor em uma chave podemos utilizar a função RegSetValueEx:

#include <windows.h>

int main()
{
HKEY chave;

if(RegOpenKey(HKEY_CURRENT_USER,"Minha Chave",&chave) != 0) // Abre a chave "Minha Chave"
 {
   MessageBox(0,"Ocorreu um erro ao abrir a chave!","Erro",0x10);
   return 1;}

if(RegSetValueEx(chave,"Meu Valor",0,REG_SZ,(LPBYTE)"LOL",3) != 0)
   MessageBox(0,"Ocorreu um erro ao escrever o valor!","Erro",0x10);
 
   RegCloseKey(chave); // Independente se ocorrer um erro ou não, ao escrever o valor, a chave precisa ser fechada.

      return 0;
}

Vejamos o trecho responsável por tentar criar o valor:

if(RegSetValueEx(chave,"Meu Valor",0,REG_SZ,(LPBYTE)"LOL",3) != 0)
   MessageBox(0,"Ocorreu um erro ao escrever o valor!","Erro",0x10);

Tenta-se escrever, na chave Minha Chave, um valor com as seguintes informações:

QuoteNome do valor  = Meu Valor
Tipo do valor  = REG_SZ
Dados do valor = LOL

A sintaxe da função é:

QuoteLONG WINAPI RegSetValueExW(HKEY valor_chave, LPCWSTR nome_valor, DWORD reservado, DWORD tipo, BYTE* dados ,DWORD tamanho);

     valor_chave:
         valor da chave na qual iremos criar o valor; pode ser uma chave raiz;

     nome_valor:
         nome (string) do valor a ser criado;

     reservado:
         é um valor reservado do sistema, DEVE SER ZERO;

     tipo:
         tipo de valor a ser criado. Pode ser:

                          REG_SZ              = string;
        REG_EXPAND_SZ  = string expandida
      REG_BINARY       = valor binário;
      REG_DWORD      = valor DWORD
      REG_MULTI_SZ   = string múltipla

     dados:
         dados que serão escritos no valor (convertido para BYTE); se estes dados forem de um tipo diferente de STRING, deve-se passar um ponteiro para uma variável que armazena tais dados;

     tamanho:
         número de bytes que serão escritos no valor.

Assim como as funções analisadas anterioremente, RegSetValueEx retorna ZERO caso o valor senha criado, ou retorna um valor DIFERENTE DE ZERO, caso algum erro ocorra.

Vamos destacar um parâmetro da função:

Quotedados:
         dados que serão escritos no valor (convertido para BYTE);

Vejamos agora como isso foi feito:

(LPBYTE)"LOL"

Acima, convertemos a string "LOL" para BYTE. Na sintaxe da função, temos: BYTE* dados - que equivale a LPBYTE.

Se você observar bem, a string "LOL" possui 3 caracteres, por isso é este valor que passamos para o argumento tamanho.

Veja um outro exemplo:

    #include <stdio.h> // Para usar printf() e scanf()
#include <string.h> // Para usar strlen()
#include <windows.h>

int main()
{
HKEY chave;

if(RegOpenKey(HKEY_CURRENT_USER,"Minha Chave",&chave) != 0)
 {
   MessageBox(0,"Ocorreu um erro ao abrir a chave!","Erro",0x10);
   return 1;}

char nome[30];
printf("Digite o seu nome:\n");
scanf("%30s",nome); // Obtém um máximo de 30 caracteres

if(RegSetValueEx(chave,"Nome",0,REG_SZ,(LPBYTE)nome,strlen(nome)) != 0)
   MessageBox(0,"Ocorreu um erro ao escrever o valor!","Erro",0x10);

   RegCloseKey(chave);

      return 0;
}

Desta vez, o programa obtém um nome digitado e o escreve na chave.

O trecho abaixo obtém o nome:

char nome[30];
printf("Digite o seu nome:\n");
scanf("%30s",nome);

O bloco abaixo tenta escrevê-lo:

if(RegSetValueEx(chave,"Nome",0,REG_SZ,(LPBYTE)nome,strlen(nome)) != 0)
   MessageBox(0,"Ocorreu um erro ao escrever o valor!","Erro",0x10);

Veja:

Quote(LPBYTE)nome -> converte de string para BYTE;
strlen(nome)   -> retorna o tamanho da string -> número de bytes que serão escritos.

Veremos a seguir, um exemplo de como escrever um valor que não seja uma string.

Retome a descrição do parâmetro:

Quotedados:
      dados que serão escritos no valor (convertido para BYTE); se estes dados forem de um tipo diferente de STRING, deve-se passar um ponteiro para uma variável que armazena tais dados;

Como não vamos escrever um valor do tipo string, devemos ter uma variável que armazene este valor e fornecer um ponteiro para ela:

#include <stdio.h> // Para usar printf() e scanf()
#include <windows.h>

int main()
{
HKEY chave;

if(RegOpenKey(HKEY_CURRENT_USER,"Minha Chave",&chave) != 0)
 {
   MessageBox(0,"Ocorreu um erro ao abrir a chave!","Erro",0x10);
   return 1;}

int numero;
printf("Digite um numero:\n");
scanf("%d",&numero);

// Utilizamos REG_DWORD pois se trata de um número e não uma string
if(RegSetValueEx(chave,"Numero",0,REG_DWORD,(LPBYTE)&numero,sizeof(numero)) != 0)
   MessageBox(0,"Ocorreu um erro ao escrever o valor!","Erro",0x10);

   RegCloseKey(chave);

      return 0;
}

Desta vez, o programa obtém um número digitado e escreve-o no valor "Numero" do tipo REG_DWORD.

O trecho abaixo obtém o número:

int numero;
printf("Digite um numero:\n");
scanf("%d",&numero);

O valor é escrito logo abaixo:

if(RegSetValueEx(chave,"Numero",0,REG_DWORD,(LPBYTE)&numero,sizeof(numero)) != 0)
   MessageBox(0,"Ocorreu um erro ao escrever o valor!","Erro",0x10);

Destacando os últimos argumentos, temos:

(LPBYTE)&numero,sizeof(numero);

A variável "numero" é do tipo inteiro e armazena os dados que iremos escrever (o número digitado).
Por ser do tipo inteiro, não poderíamos fazer:

(LPBYTE)numero;

Devemos passar o endereço dessa variável através do operador &:

(LPBYTE)№

Novamente, por ser do tipo inteiro, não poderíamos fazer:

strlen(numero); // Observe que o heade string.h não foi incluído justamente porque é desnecessário

Nesta ocasião, devemos passar o tamanho que a variável ocupa através do operador sizeof():

sizeof(numero);



4) Obtendo um valor

Veremos como obter dados de um valor.

#include <windows.h>

int main()
{
HKEY chave;

if(RegOpenKey(HKEY_CURRENT_USER,"Minha Chave",&chave) != 0)
 {
   MessageBox(0,"Ocorreu um erro ao abrir a chave!","Erro",0x10);
   return 1;}


char nome[30];
DWORD tipo, tamanho_buffer = 30;

if(RegQueryValueEx(chave,"Nome",0,&tipo,(LPBYTE)nome,&tamanho_buffer) != 0)
   MessageBox(0,"Ocorreu um erro ao obter o valor!","Erro",0x10);
else
   MessageBox(0,nome,"O valor é:",0x40);

   RegCloseKey(chave);

      return 0;
}


Vamos analisar:

char nome[30];
DWORD tipo, tamanho_buffer = 30;
A variável "nome" será utilizada para armazenar os dados contidos no valor que se deseja obter;

A variável "tipo" é utilizada para armazenar o tipo (no registro) do valor que se deseja obter;

Por fim, a variável "tamanho_buffer" contém o tamanho em bytes que a variável "nome" contém, no caso 30.

Vejamos a sintaxe:

QuoteLONG WINAPI RegQueryValueExW(HKEY valor_chave, LPCWSTR nome_valor, DWORD reservado, DWORD* pt_tipo, BYTE* buffer, DWORD * pt_tamanho);

     valor_chave:
         valor da chave na qual iremos criar o valor; pode ser uma chave raiz;

     nome_valor:
         nome (string) do valor a ser criado;

     reservado:
         é um valor reservado do sistema, DEVE SER ZERO;

     pt_tipo:
         ponteiro para uma variável do tipo DWORD que irá armazenar o tipo de dado do valor, no registro;
 
     buffer:
         ponteiro para a variável (buffer) que irá armazenar os dados do valor, convertido para BYTE;

     pt_tamanho:
         ponteiro para uma variável do tipo DWORD que contém o número de bytes que o buffer possui.


A função RegSetValueEx retorna ZERO caso o valor senha criado, ou retorna um valor DIFERENTE DE ZERO, caso algum erro ocorra.

Veja:

if(RegQueryValueEx(chave,"Nome",0,&tipo,(LPBYTE)nome,&tamanho_buffer) != 0)
   MessageBox(0,"Ocorreu um erro ao obter o valor!","Erro",0x10);
else
   MessageBox(0,nome,"O valor é:",0x40);

Tenta-se armazenar em "nome" os dados contidos no valor "Nome" do registro.

Destacando os três últimos argumentos:

&tipo,(LPBYTE)nome,&tamanho_buffer

Quote&tipo = endereço da variável "tipo" que irá armazenar o tipo de dado do valor;

(LPBYTE)nome    = buffer que irá armazenar os dados, convertido para BYTE;

&tamanho_buffer =  endereço da variável "tamanho_buffer" que contém o número de bytes que o buffer possui.

Note que, embora o parâmetro "buffer" exija um ponteiro para uma variável, não precisamos fazer:

(LPBYTE)&nome

Quando temos uma string, o processo é feito implicitamente.

Outro exemplo:

#include <stdio.h> // para usar printf()
#include <windows.h>

int main()
{
HKEY chave;

if(RegOpenKey(HKEY_CURRENT_USER,"Minha Chave",&chave) != 0)
 {
   MessageBox(0,"Ocorreu um erro ao abrir a chave!","Erro",0x10);
   return 1;}


int numero;
DWORD tipo, tamanho_buffer = sizeof(numero);

if(RegQueryValueEx(chave,"Numero",0,&tipo,(LPBYTE)&numero,&tamanho_buffer) != 0)
   MessageBox(0,"Ocorreu um erro ao obter o valor!","Erro",0x10);
else
 // Não podemos utilizar MessageBox neste caso, pois "numero" é um inteiro e não uma string =)
  printf("O valor e': %d",numero);
 
   RegCloseKey(chave);

      return 0;
}

Agora, tentamos obter os dados do valor "Numero".

Nas variáveis, temos:

int numero; // buffer
DWORD tipo, tamanho_buffer = sizeof(numero); // tamanho em bytes que a variável ocupa

Em seguida:

if(RegQueryValueEx(chave,"Numero",0,&tipo,(LPBYTE)&numero,&tamanho_buffer) != 0)
   MessageBox(0,"Ocorreu um erro ao obter o valor!","Erro",0x10);
else
 // Não podemos utilizar MessageBox neste caso, pois "numero" é um inteiro e não uma string =)
  printf("O valor e': %d",numero); // Mostra o valor

Novamente, obtendo os três últimos argumentos:


Quote&tipo -> endereço da variável "tipo";

(LPBYTE)&numero -> endereço da variável "numero" -> como não é uma
string, o uso do operador & é obrigatório;

&tamanho_buffer -> endereço da variável "tamanho_buffer";

5) Deletando um valor

Para deletar um valor, utilizamos a função RegDeleteValue():

#include <windows.h>

int main()
{
HKEY chave;

if(RegOpenKey(HKEY_CURRENT_USER,"Minha Chave",&chave) != 0)
 {
   MessageBox(0,"Ocorreu um erro ao abrir a chave!","Erro",0x10);
   return 1;}


if(RegDeleteValue(chave,"Nome") != 0) // Tenta deletar o valor "Nome" contido em "Minha Chave"
   MessageBox(0,"Ocorreu um erro ao deletar o valor 'Nome'","Erro",0x10);
 
if(RegDeleteValue(chave,"Numero") != 0) // Tenta deletar o valor "Numero" contido em "Minha Chave"
   MessageBox(0,"Ocorreu um erro ao deletar o valor 'Numero'","Erro",0x10);

   RegCloseKey(chave);

      return 0;
}

Sintaxe:

QuoteLONG WINAPI RegDeleteValue(HKEY valor_chave, LPCWSTR valor_nome);

     
     valor_chave:
           valor da chave na qual iremos deletar um valor;

    valor_nome:
           nome (string) do valor a ser deletado.

Se o valor for deletado, o valor ZERO é retornado, do contrário, um valor DIFERENTE DE ZERO é retornado.


6) Deletando uma chave

Para deletar uma chave, utilizamos a função RegDeleteKey():

#include <windows.h>
int main()
{

if(RegDeleteKey(HKEY_CURRENT_USER,"Minha Chave") != 0)
  MessageBox(0,"Erro ao deletar a chave!","Erro",0x10);

      return 0;
}

A sintaxe é:

QuoteLONG WINAPI RegDeleteKey(HKEY valor_chave, LPCWSTR subchave_nome);

     
     valor_chave:
           valor da chave na qual iremos deletar um valor; pode ser uma chave raiz;

     subchave_nome:
           nome (string) da subchave a ser deletada.

Se a chave for deletada, o valor ZERO é retornado, do contrário, um valor DIFERENTE DE ZERO é retornado.

Parece bem simples não? De fato, relativamente é.
Nos Windows 9X/ME, todos as subchaves e valores da chave "Minha Chave" seriam deletados.

O problema ocorre nos Windows 2000/NT/XP, quando há subchaves dentro de uma chave que queremos deletar. Se a chave conter subchaves, para deletá-la, devemos deletar todas as suas subchaves indivualmente antes.

Veja:

#include <windows.h>

int main()
{
HKEY chave;

if(RegCreateKey(HKEY_CURRENT_USER,"Minha Chave\\SubChave",&chave) != 0)
 {
   MessageBox(0,"Ocorreu um erro ao criar a chave!","Erro",0x10);
   return 1;}

RegCloseKey(chave);   
         
      return 0;
}
     

No exemplo acima, criaríamos a chave "Minha Chave" contendo a subchave "SubChave".

Se tentarmos utilizar o programa abaixo para deletar a chave "Minha Chave" não teríamos êxito:

#include <windows.h>
int main()
{

if(RegDeleteKey(HKEY_CURRENT_USER,"Minha Chave") != 0)
  MessageBox(0,"Erro ao deletar a chave!","Erro",0x10);

      return 0;
}

Para solucionar o problema, podemos fazer:

A) Deletar a subchave previamente:

#include <windows.h>
int main()
{
HKEY chave;

if(RegOpenKey(HKEY_CURRENT_USER,"Minha Chave",&chave) != 0) // Abre a chave
 {
   MessageBox(0,"Ocorreu um erro ao abrir a chave!","Erro",0x10);
   return 1;}

if(RegDeleteKey(chave,"SubChave") != 0) // Deleta subchave
   MessageBox(0,"Erro ao deletar a chave SubChave!","Erro",0x10);

   RegCloseKey(chave); // Fecha a chave "Minha Chave"

if(RegDeleteKey(HKEY_CURRENT_USER,"Minha Chave") != 0) // Deleta a chave de HKEY_CURRENT_USER
  MessageBox(0,"Erro ao deletar a chave Minha Chave!","Erro",0x10);

      return 0;
}

B) Para poupar trabalho, pode-se utilizar a função SHDeleteKey contida no header "swlwapi.h":

#include <windows.h>
#include <shlwapi.h> // Para usar SHDeleteKey
int main()
{
HKEY chave;


if(SHDeleteKey(HKEY_CURRENT_USER,"Minha Chave") != 0) // Deleta a chave de HKEY_CURRENT_USER
  MessageBox(0,"Erro ao deletar a chave Minha Chave!","Erro",0x10);
      return 0;
}

A sintaxe da função é:

QuoteLONG WINAPI SHDeleteKey(HKEY valor_chave, LPCWSTR subchave_nome);

     
     valor_chave:
           valor da chave na qual iremos deletar um valor; pode ser uma chave raiz;

     subchave_nome:
           nome (string) da subchave a ser deletada.


Se a chave for deletada, o valor ZERO é retornado, do contrário, um valor DIFERENTE DE ZERO é retornado.

Da maneira acima, todas as subchaves e valores de "Minha Chave" também seriam deletados.

Algo importante:

Se optarmos por utilizar a função SHDeleteKey, devemos incluir no LINKER do compilador, a lib "shlwapi".

No Dev C++, o fazemos da seguinte maneira:

Quote1. Menu Ferramentas -> Opções do compilador;
2. Marca-se a caixa: "Adicionar estes comandos à linha de comando do linker";
3. Adiciona-se, na caixa, "-l shlwapi"
4. OK =)


7) Listando todas as subchaves de uma chave:

#include <windows.h>
int main()
{
HKEY chave;
char nome_chave[256];
int i = 0;

if(RegOpenKey(HKEY_CURRENT_USER,"",&chave) != 0)
 {
   MessageBox(0,"Ocorreu um erro ao abrir a chave!","Erro",0x10);
   return 1;}


while(RegEnumKey(chave,i,nome_chave,256) == 0)
{
MessageBox(0,nome_chave,"Nome da chave:",0);
i++;
}
      return 0;
}

Veja as variáveis:

char nome_chave[256];
int i = 0;

A variável "nome_chave" irá armazenar o nome da chave atual, enquanto a variável "i" armazenará número ID da chave.

Iremos listar todas as subchaves contidas em HKEY_CURRENT_USER:

if(RegOpenKey(HKEY_CURRENT_USER,"",&chave) != 0)
 {
   MessageBox(0,"Ocorreu um erro ao abrir a chave!","Erro",0x10);
   return 1;}

Para abrimos uma chave raiz, basta passar o segundo argumento como vazio: "".

Listamos todas as subchaves:

while(RegEnumKey(chave,i,nome_chave,256) == 0) // Enquanto houver subchave
{
MessageBox(0,nome_chave,"Nome da chave:",0);
i++; // Incrementa variável -> próxima chave
}

A sintaxe é:

QuoteLONG WINAPI RegEnumKeyW(HKEY valor_chave,DWORD chave_ID,LPWSTR buffer,DWORD tam_buffer);

   
     valor_chave:
           valor da chave na qual estão as subchaves que queremos listar; pode ser uma chave raiz;

     chave_ID:
           número ID da chave, começando por ZERO;

     buffer:
           buffer que irá armazenar o nome da chave;

     tam_buffer:
           tamanho do buffer em bytes.

Para cada chamada à função, se a subchave requisitada for retornada com êxito, a função retorna ZERO, senão, retornado um valor DIFERENTE DE ZERO.

8) Listando todos os valores e dados de uma chave

#include <windows.h>
int main()
{
HKEY chave;

char nome_valor[256] = {0};
char dados_valor[256] = {0};

DWORD nome_tam = 256;
DWORD dados_tam = 256;
DWORD tipo;
int i = 0;

// Tenta abrir a chave -> contém itens de inicialização do windows
if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&chave) != 0)
 {
   MessageBox(0,"Ocorreu um erro ao abrir a chave!","Erro",0x10);
   return 1;}


while(RegEnumValue(chave,i,nome_valor,&nome_tam,0,&tipo,(LPBYTE)dados_valor,&dados_tam) == 0)
{
 if(tipo == REG_SZ)
 MessageBox(0,dados_valor,nome_valor,0);

nome_tam = 256;
dados_tam = 256;
i++;

}

      return 0;
}

Na seção das variáveis temos:

char nome_valor[256] = {0};
char dados_valor[256] = {0};

DWORD nome_tam = 256;
DWORD dados_tam = 256;
DWORD tipo;
int i = 0;


Quotenome_valor  -> armazenar o nome de cada valor;
dados_valor -> armazenar os dados de cada valor;
nome_tam   -> tamanho do buffer que irá armazenar o nome do valor;
dados_tam  -> tamanho do buffer que irá armazenar os dados do valor;
tipo            -> armazenar o tipo de dado;
i                 -> número ID do valor;

Veja :

while(RegEnumValue(chave,i,nome_valor,&nome_tam,0,&tipo,(LPBYTE)dados_valor,&dados_tam) == 0)
{
 if(tipo == REG_SZ)
 MessageBox(0,dados_valor,nome_valor,0);

nome_tam = 256;
dados_tam = 256;
i++;

}


No trecho, tenta-se obter o valor (e seus respectivos dados), que está situado na posição "i". 

É verificado se o tipo é string:

if(tipo == REG_SZ)
 MessageBox(0,dados_valor,nome_valor,0); // Mostra valor e dados

A cada interação do loop:

// A abaixo é necessária para fazer com que a função obtenha o próxima valor:
nome_tam = 256; // redefine o tamanho do buffer "nome_valor"
dados_tam = 256; // redefine o tamanho do buffer "dados_tam"

i++; // Incrementa ID do valor a ser obtido

A sintaxe é:

QuoteLONG WINAPI RegEnumValue(HKEY valor_chave, DWORD valor_ID,LPWSTR nome_valor, PDWORD pt_valortam,PDWORD Reservado,PDWORD  pt_tipo, LPBYTE dados_valor,PDWORD pt_dadostam);


     valor_chave:
         valor da chave na qual queremos obter os valores; pode ser uma chave raiz;

     valor_ID:
         número ID do valor;

    nome_valor:
         a variável (buffer - string) que irá armazenar o nome do valor;

     pt_valortam:
         ponteiro para uma variável do tipo DWORD que contém o número de bytes que o buffer acima possui.

     reservado:
         é um valor reservado do sistema, DEVE SER ZERO;

     pt_tipo:
         ponteiro para uma variável do tipo DWORD que irá armazenar o tipo de dado do valor, no registro;

    dados_valor:
         ponteiro para a variável (buffer) que irá armazenar o nome do valor;

     pt_dadostam:
         ponteiro para uma variável do tipo DWORD que contém o número de bytes que o buffer acima possui.


Para cada chamada à função, se o valor requisitada for retornado com êxito, a função retorna ZERO, senão, retornado um valor DIFERENTE DE ZERO.


Bem, apesar de existirem outras funções e extensões para as citadas no artigo, basicamente, a manipulação do registro é feita da forma como foi apresentada no texto.

Lolz, lembre-se: Tome cuidado ao manipular o registro do windows =)

Bye ;)

insanity

Registro do Windows é muito estanho, depois que você acostuma fica relativamente facil ;)

Watila


Anonymous

opa...

Cara tire uma dúvida minha por favor...Estudo o C++ em casa sozinho e algumas linhas acabam confundindo a gente, por exemplo:

#include     -----e as outras bibliotecas??? ??? ??? ??? ???
int main()
{
HKEY chave;   

   -----> Essa variável não deviria ter sido definida no início.....conheço pouco sobre , se vocês porem tirar essa dúvida minha....vlw

Dark_Side

Hi,

Quote from: "fuçador_csf"opa...

Cara tire uma dúvida minha por favor...Estudo o C++ em casa sozinho e algumas linhas acabam confundindo a gente, por exemplo:

#include     -----e as outras bibliotecas??? ??? ??? ??? ???
int main()
{
HKEY chave;   

   -----> Essa variável não deviria ter sido definida no início.....conheço pouco sobre , se vocês porem tirar essa dúvida minha....vlw

A quais outros headers você se refere? Para utilizar as funções de manipulação do registro em C/C++ é necessário incluir o header winreg.h que, por sua vez, está definido em windows.h. Por este motivo, o único header que devemos incluir no código obrigatoriamente é windows.h ou winreg.h de forma direta.

Quanto à segunda dúvida: existem dois estilos básicos de variáveis, que são a variável local e a variável global.

Quando declaramos uma variável dentro de uma função, dizemos que esta variável é local; ao contrário de quando essa mesma variável é declarada fora de qualquer função, o que a define como variável global.


No exemplo que você citou, a variável chave é declarada dentro da função main(), portanto, trata-se de uma variável local que só pode ser acessada dentro da função na qual foi declarada (main):

#include <windows.h>
int main()
{
HKEY chave;     // Declara a variável "chave" como local
}

Observe o exemplo:


#include <windows.h>

HKEY chave;     // Declara a variável "chave" como global
int main()
{
}

Neste exemplo, a variável "chave" é declarada como global. Isto significa que não só a função main() como qualquer outra função dentro do programa poderá ter acesso à variável - o que não é possível quando declaramos uma variável local.

Sendo assim, tanto faz declarar a variável "chave" como local ou global.

Seria isso xD

Caso não tenha respondido às suas dúvidas ou ainda persistirem basta postar novamente =)

Bye.

Korndog

Eu tentei fazer meu próprio código seguindo os princípios básicos, ele grava a chave, porém não retorna resultado....

Quote#include <windows.h>
#include<stdio.h>

int main(){
  char nome[30];
  DWORD tipo, tamanho_buffer = 30;
 
  HKEY chave;
  TCHAR szPath[MAX_PATH];
  GetModuleFileName(NULL,szPath,MAX_PATH);
 
  RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&chave);
  RegSetValueEx(chave,"Korndog", 0, REG_SZ, (LPBYTE)szPath, sizeof(szPath));                                                                                               
  RegCloseKey(chave);   

  if(RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run\\",&chave) != 0){
    printf("Ocorreu um erro ao abrir a chave!\n");
  } else {
    if(RegQueryValueEx(chave,"Korndog",0,&tipo,(LPBYTE)nome,&tamanho_buffer) != 0){
      printf("Ocorreu um erro ao obter o valor!\n");
    } else {
      printf("O valor e': %d\n",nome);
    }
  }

  RegCloseKey(chave);   
         
  system("pause");
}

Alguém se habilita a me ajudar ?
Grato.  :)
In life... there's no undo.

Menor