Programowanie rejestru

RafalS

Napisałem ten artykuł, bo nigdzie podobnego nie znalazłem. Rzecz będzie dotyczyć programowania rejestru. Na początek muszę powiedzieć, że zabawa z rejestrem to jak bawienie się zapałkami, jeśli nie wiesz, kiedy ich używać to się nie baw. Dodam od razu, że za wszelkie szkody wynikłe z tego artykułu nie odpowiadam. Dobra do konkretów.

Ogólnie o rejestrze:
Rejestr jest to taka baza danych systemu operacyjnego windows, w której przechowywane są informacje o sprzęcie użytkownikach itd. Tak naprawdę rejestr jest przechowywany w kilku plikach których ręczna edycja jest nie możliwa.

Pliki rejestru:
Windows98
user.dat,system.dat

WindowsMe
Classes.dat, User.dat , System.dat

Windows2000,WindowsXp,Windows2003
Jest to bardziej rozdrobnione ze względu na bezpieczeństwo. Nie będę ich wszystkich tu wypisywał, ale ich listę można zobaczyć tu:
http://support.microsoft.com/default.aspx?scid=kb;PL;256986

Struktura rejestru:
Informacje w rejestrze podzielone są na klucze, które zawierają swoje podklucze i wartości, podklucze mogą zawierać swoje podklucze i wartości. Powstaje taka hierarchiczna struktura drzewa. Każdy klucz posiada przynajmniej jedną wartość zwaną wartością domyślną, która nie posiada nazwy, pozostałe wartości muszą posiadać nazwę. Każda wartość posiada również swój typ(o tym za chwile). Jest kilka kluczy głównych(te widziane, zaraz po otwarciu edytora rejestru).

HKEY_CLASSES_ROOT ? przechowuje min zarejestrowane w systemie typy plików.
Można przy pomocy tego klucza rejestru np. definiować własne polecenia w menu kontekstowym(tym co się pokazuje po kliknięciu prawym klawiszem) dla określonego typu plików.

HKEY_USERS- przechowuje wszelkie informacje związane z użytkownikami. W windows98 nazwy użytkowników były jawnymi podkluczami rejestru, modyfikowanie ich było często jedyną możliwością ograniczenia praw użytkowników. W windowsach 2000/xp/2003 jest inaczej. Informacje o kontach użytkowników są przechowywane w rejestrze w podkluczach których nazwy są to tzw. Identyfikatory zabezpieczeń SID. Ciekawe jest to, że adminisrator uruchamiając edytor rejestru spod swojego konta nie widzi gałęzi innych użytkowników.

Aby mógł je modyfikowć z pod swojego konta musi załadować odpowiednią gałąź rejestru(musi znać identyfikator SID użytkownika):Jak?
Ustawić aktywny klucz na HKEY_USERS i File->Load Hive wskazać plik ntuser.dat użytkownika podać SID i już może modyfikować rejestr. Potem tą gałąź należy później zwolnić.

HKEY_CURRENT_USER- tworzony podczas logowania do systemu zawiera ustawienia bieżącego użytkownika.
HKEY_LOCAL_MACHINE- zawiera wszysko związane z lokalnym komputerem tj. sprzęt,sterowniki,oprogramowanie.

HKEY_CURRENT_CONFIG ?zawiera min informacje o profilu sprzętu uruchamianego przy starcie, oraz podobno ta gałąź dotyczy mechanizmu plug&play. Nigdy jakoś w niej nic nie zmieniałem.

HKEY_DYN_DATA- klucz występuje tylko w win98/Me. Większość informacji tam zawartych dostępna jest tylko dla systemu.

Informacje zawarte w rejestrze często się powtarzają(np. klucz główny HKEY_CURRENT_USER jest kopą klucza HKEY_USERS\nazwa użytkownika(win98))

Dodatkowe informacje o kluczach rejestru znajdziesz tu:
http://windows.home.pl/alchemia/rejestr2.htm

Klucze można odnieś do katalogów natomiast wartości do plików bo to w końcu one zawierają informacje. No właśnie jakie są rodzaje wartości przechowywane w rejestrze omówię tylko najważniejsze , te których będę używał w programie.

Wartości przechowywane w rejestrze

REG_DWORD ?jest to po prostu 32bitowa liczba.

REG_SZ- wartość jest przechowywana jako ciąg zakończony znakiem pustym(Null-terminated string)
np w klucczu
HKEY_CLASSES_ROOT\AcroExch.FDFDoc\shell\open\command
występuje wartość domyśna która wynosi
"F:\Program Files\Adobe\Acrobat 5.0\Reader\AcroRd32.exe" "%1"
Gdy użytkownik kliknie prawym klawiszem na plik *.pdf i wybierze open to znaczek %1 zastąpiony nazwą edytowanego pliku i uruchomiona zostanie odpowiednia aplikacja

REG_EXPAND_SZ- jest to również ciąg zakończony znakiem pustym tylko mogący zawierać podciągi znaków które zawierają odwołania do zmiennych środowiskowych. Które pod winxp można podejrzeć tak:
panel sterowania->system->zaawansowane->zmienne środowiskowe
Ciągi te są zamieniane danymi gdy wystąpi odpowiednie wywołanie aplikacji.
Np. W kluczu
HKEY_CLASSES_ROOT\batfile\shell\edit\command
występuje wartość domyślna która wynosi
%SystemRoot%\System32\NOTEPAD.EXE %1 .
Gdy użytkownik kliknie prawym klawiszem na plik *.bat i wybierze edit to ciąg %SystemRoot% zostanie zastąpiony ścieżką do folderu w którym zainstalowano windows np. c:\WINDOWS, a znaczek %1 zastąpiony nazwą edytowanego pliku. Wartości tego typu nie występowały w win98.

REG_MULTI_SZ- są to tak zwane multistringi. Składają się z kilku stringów odzielonych od siebie znakiem pustym i zakończonych dwoma znakami pustymi. W rejestrze wygląda to np. tak:
ACPI\AuthenticAMD_-x86_Family_6_Model_6
*AuthenticAMD
-x86_Family_6_Model_6
ACPI\AuthenticAMD
-x86_Family_6
*AuthenticAMD
-x86_Family_6
ACPI\AuthenticAMD
-x86
*AuthenticAMD
-_x86
Wartości te również nie występowały w win98.

REG_BINARY- dane przechowywane w postaci binarnej(ciąg jakichś bajtów).Wartości te mogą w rejestrze wyglądać np tak:

0000  3f   00   00   00   00   01   00   00 ?.......
0008  01   01   00   00   19   00   00   00 ........
0010  01   00   00   00   02   00   00   00 ........
0018  03   00   00   00   04   00   00   00 ........
0020  05   00   00   00   06   00   00   00 ........
0028  07   00   00   00   08   00   00   00 ........
0030  09   00   00   00   0a   00   00   00 ........
0038  0b   00   00   00   0c   00   00   00 ........
0040  0d   00   00   00   0e   00   00   00 ........
0048  0f   00   00   00   10   00   00   00 ........
0050  11   00   00   00   12   00   00   00 ........
0058  13   00   00   00   14   00   00   00 ........
0060  15   00   00   00   16   00   00   00 ........
0068  17   00   00   00   1a   00   00   00 ........
0070  18   00   00   00   1b   00   00   00 ........
0078  1c   00   00   00   1d   00   00   00 ........
0080  1e   00   00   00   1f   00   00   00 ........
0088  20   00   00   00   23   00   00   00  ...#...
0090  24   00   00   00   25   00   00   00 $...%...
0098  26   00   00   00   27   00   00   00 &...'...
00a0  28   00   00   00   29   00   00   00 (...)...
00a8  2a   00   00   00   2b   00   00   00 *...+...
00b0  2c   00   00   00   2d   00   00   00 ,...-...
00b8  2e   00   00   00   2f   00   00   00 ..../...
00c0  30   00   00   00   31   00   00   00 0...1...
00c8  32   00   00   00   33   00   00   00 2...3...
00d0  34   00   00   00   35   00   00   00 4...5...
00d8  36   00   00   00   37   00   00   00 6...7...
00e0  38   00   00   00   39   00   00   00 8...9...
00e8  3a   00   00   00   3b   00   00   00 :...;...
00f0  3c   00   00   00   3d   00   00   00 <...=...
00f8  3e   00   00   00   3f   00   00   00 >...?...
0100                                             

No więc co oznaczają poszczególne wartości:

Tak naprawde istotne jest osiem środkowych kolumn,które zawierają wartości przechowywane w kolejnych bajtach,zapisane szesnastkowo.
Wartości te są liczone od lewej do prawej.Kolumna z prawej strony zawiera znaki jakie byśmy widzieli wpisując wartości kolejnych bajtów,przy czym znaki sterujące(0-1F) są wyświetlane jako kropki.Np wartość 32(0x20) oznacza kod spacji,więc widzimy puste miejsce.Kolumna z prawej strony jest tak jakby liczbą porządkową(numerami kolejnych komórek(bajtów)) zapisaną szesnastkowo.

Max rozmiary elementów rejestru:

Nazwa klucza 255 znaków
Nazwa wartości winxp/win2003: 16,383 znaków
Windows 2000: 260 Znaków ANSI lub 16,383 znaków w unikodzie.
Windows Me/98/95: 255 znaków
Wartości win2000/xp/2003 dostępna pamięć
Windows Me/98/95: 16,300 bajtów.

Wszystkie wartości jednego klucza mają w winMe/98/95 ograniczenie do max 64KB.

modyfikowanie rejestru

1.poprzez edytor rejestru
start->uruchom->regedit

Dostępne są dwa edytory rejestru o różnicach między nimi można poczytać tu:
http://support.microsoft.com/default.aspx?scid=kb;PL;141377

2.Poprzez pliki*.reg

Importując do rejestru plików *.reg należy pamiętać ,że importowanie do rejestru odbywa się zgodnie z regułą scalaj(merge), a nie wykasuj wszystkie wartości i wstaw na to miejsce, czyli zamieniane są tylko wartości które mają taką samą nazwę jak w pliku *.reg pozostałe wartości w danym kluczu są pozostawiane bez zmian. Pliki *.reg importujemy do rejestru przez polecenie scalaj(prawy klawisz lub klikając dwa razy).
Aha w win 98 zablokowanie użytkownikowi dostępu do edytora rejestru, nie powodowało, że użytkownik nie mógł modyfikować rejestru przy użyciu plików reg. W win 2000 już podobno tak dobrze nie ma.

3.Pliki sterowników *.inf

Sekcja[Install] zawiera sekcje [Add Registry] i [Delete Registry] służące do modyfikowania rejestru.

4.Modyfikowanie z poziomu programu przez zastosowanie funkcji WinApi(to nas będzie interesowało)

Zanim weźmiemy się za programowanie troszeczkę o prawach dostępu do kluczy rejestru.
Aby móc cokolwiek zrobić(utworzyć lub skasować przeglądać podklucze lub wartości) w jakimś kluczu musimy go otworzyć z odpowiednimi prawami.

Prawa dostępu do kluczy rejestru

Prawa dostępu do kluczy rejestru możemy podzielić na:
1.Standardowe prawa dostępu do chronionych obiektów:
STANDARD_RIGHTS_WRITE,
STANDARD_RIGHTS_READ.
O nich nie będę pisał, jak ktoś chce to może o nich poczytać tu:
http://msdn.microsoft.com/library/en-us/secauthz/security/standard_access_rights.asp

2.Prawa specyficzne dla kluczy rejestru:

KEY_CREATE_SUB_KEY- zezwolenie na tworzenie(kasowanie) podkluczy w kluczu który został otwarty z tym prawem.

KEY_ENUMERATE_SUB_KEYS- zezwolenie na wyliczanie(kolejne odczytywanie)podkluczy w kluczu ,który został otwarty z tym prawem.

KEY_SET_VALUE- zezwolenie na tworzenie, kasowanie, ustawianie wartości w kluczu, który został otwarty z tym prawem.

KEY_QUERY_VALUE- zezwolenie na przepytywanie(przeszukiwanie) wartości w kluczu otwartym z tym prawem.

KEY_NOTIFY- Required to request change notifications for a registry key or for subkeys of a registry key.(nie bardzo wiem o co chodzi)

KEY_READ- otwarcie klucza z tym prawem to tak jakby go otwarto z tymi wszystkimi prawami : STANDARD_RIGHTS_READ,
KEY_QUERY_VALUE,
KEY_NOTIFY,
KEY_ENUMERATE_SUB_KEYS.
Czyli generalna zgoda na odczyt wartości, podkluczy.

KEY_EXECUTE- równoważne KEY_READ.

KEY_WRITE- otwarcie klucza z tym prawem to tak jakby go otwarto z tymi wszystkimi prawami : STANDARD_RIGHTS_WRITE,
KEY_SET_VALUE,
KEY_CREATE_SUB_KEY .
Czyli generalna zgoda na zapis, kasowanie wartości podkluczy.

KEY_CREATE_LINK- prawo tworzenia dowiązań symbolicznych, zarezerwowane dla systemu.

KEY_ALL_ACCESS- otwarcie klucza z tym prawem to tak jakby go otwarto z tymi wszystkimi prawami: STANDARD_RIGHTS_REQUIRED,
KEY_QUERY_VALUE,
KEY_SET_VALUE,
KEY_CREATE_SUB_KEY,
KEY_ENUMERATE_SUB_KEYS,
KEY_NOTIFY,
KEY_CREATE_LINK.
Czyli zezwolenie na dostęp wszelkiego rodzaju.

Predefiniowane uchwyty kluczy

Jak już mówiłem aby móc cokolwiek robić z rejestrem musimy otworzyć odpowiedni klucz, wtedy pobieramy sobie tzw. Uchwyt(Handle) dzięki któremu możemy się dostać do tego klucza. Po wszelkich operacjach których dokonamy na danym kluczu powinniśmy go zwrócić czyli po prostu zamknąć klucz. Klucze główne posiadają predefiniowane uchwyty, więc można je traktować jako otwarte i nie trzeba ich zamykać. Lista predefiniowanych uchwytów:

HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
HKEY_DYN_DATA tylko win95/win98/Me

Dobra dość ględzenia trzebaby napisać jakiś kod.
Napiszemy klasę do obsługi rejestru.Klasa ta będzie przechowywana w pliku nagłówkowym "rejestr.h.",który będzie dołączany do pliku rejestr.cpp. zawierającego główny kod programu.

0to wygląd pliku rejestr.h bez definicji funkcji składowych klasy które,będę umieszczał sukcesywnie podczas ich omawiania.

#include <iostream.h>
#include <windows.h>
#include <string.h>
#include<shlwapi.h>
//rodzaj informacji wykorzystane w funkcji info_o_kluczu
#define tylko_wartosci                                    1   //001
#define tylko_nazwy_wartosci                              2   //010
#define nazwy_wartosci_wartosci                           3   //011
#define tylko_podklucze                                   4   //100
#define podklucze_wartosci                                5   //101
#define podklucze_nazwy_wartosci                          6   //110
#define podklucze_nazwy_wartosci_wartosci                 7   //111

//gdzie zapisać wykorzystane w funkcji info_o kluczu
#define wypisz_na_ekran                             1 //001
#define zapisz_do_pliku                             2 //010

#define MAX_DLUGOSC_KLUCZA          255
#define MAX_DLUGOSC_NAZWY_WARTOSCI  16383
#define MAX_DLUGOSC_WARTOSCI        16000


//------------------------------------------------------------------------------
class rejestr
{
 public:
    void info_o_kluczu(HKEY       uchwyt_klucza_nadrzednego,
                       LPCTSTR              nazwa_podklucza,
                       int                rodzaj_informacji,
                       int                    gdzie_zapisac);

    void utworz_klucz(HKEY        uchwyt_klucza_nadrzednego,
                      LPCTSTR                  nazwa_klucza,
                      DWORD          prawa_dostepu_do_klucz);

    void usun_klucz(HKEY          uchwyt_klucza_nadrzednego,
                    LPCTSTR                    nazwa_klucza);

    void usun_wartosc(HKEY        uchwyt_klucza_nadrzednego,
                      LPCTSTR               nazwa_podklucza,
                      LPCTSTR                nazwa_wartosci);

   void dodaj_wartosc(HKEY        uchwyt_klucza_nadrzednego,
                      LPCTSTR               nazwa_podklucza,
                      LPCTSTR                nazwa_wartosci,
                      DWORD                   wartosc_DWORD);

   void dodaj_wartosc(HKEY        uchwyt_klucza_nadrzednego,
                      LPCTSTR               nazwa_podklucza,
                      LPCTSTR                nazwa_wartosci,
                      char                     * wartosc_SZ);

   void dodaj_wartosc(HKEY        uchwyt_klucza_nadrzednego,
                      LPCTSTR               nazwa_podklucza,
                      LPCTSTR                nazwa_wartosci,
                      char                  * wartosc_EX_SZ,
                      int                  dla_rozroznienia);

   void dodaj_wartosc(HKEY        uchwyt_klucza_nadrzednego,
                      LPCTSTR               nazwa_podklucza,
                      LPCTSTR                nazwa_wartosci,
                      char                 ** wartosc_ML_SZ);

   void dodaj_wartosc(HKEY        uchwyt_klucza_nadrzednego,
                      LPCTSTR               nazwa_podklucza,
                      LPCTSTR                nazwa_wartosci,
                      BYTE                    * wartosc_BIN,
                      int                      ilosc_bajtow);
};
//------------------------------------------------------------------------------

Widzimy tutaj funkcje składowe których nazwy mówią same za siebie.Będą one po kolei omówione. Funkcja dodaj_wartość jest funkcją przeładowywaną tzn istnieje kilka różnych definicji funkcji funkcji o tej samej nazwie. Podczas wywołania funkcji definicja o którą chodzi jest odszukiwana na podstawie listy parametrów.

Omawianie rozpocznijmy od funkcji usuwającej wskazany klucz z rejestru, klucz ten może zawierać podklucze oraz wartości.Oto kod:

//------------------------------------------------------------------------------
//funkcja wymaga biblioteki shlwapi.dll
//przekonwertowałem ją na biblioteke shlwapi.lib
//przy pomocy programiku implib(razem z Builderem)
//poleceniem  implib shlwapi.lib shlwapi.dll
//i dodałem do projektu
//funkcja wymaga prawa tworzenia(kasowania) podkluczy w kluczu nadrzędnym z
//którego kasujemy podklucz
//KEY_CREATE_SUB_KEY

void rejestr::usun_klucz(HKEY          uchwyt_klucza_nadrzednego,
                LPCTSTR                    nazwa_klucza)
{
  if(SHDeleteKey(uchwyt_klucza_nadrzednego,nazwa_klucza)==ERROR_SUCCESS)
      cout << "Klucz wraz z podkluczami zostal usuniety";
    else
      {
        cout << "Operacja nieudana, albo podany klucz nie istnieje,\n\n";
        cout << "albo nie masz odpowiednich praw by go skasowac. ";
      }
    cin.get();
}
//------------------------------------------------------------------------------

Przeczytaj wymagania tej funkcji opisane powyżej.Kod nie wymaga wielkich wyjaśnień funkcja SHDeleteKey,która jest odpowiedzialna za kasowanie klucza zwraca wartość ERROR_SUCCESS gdy usunięcie klucza się ppowiedzie.Może kilka słów o parametrach funkcji:
uchwyt_klucza_nadrzednego może być jednym z uchwytów predefiniowanych wtedy korzystający z funkcji nie musi się martwić o otwieranie, zamykanie klucza,lub może to być również uchwyt jakigoś dowolnego klucza,ale aby go uzyskać należy otworzyć lub utworzyć klucz.Nazw klucza jest typu LPCSTR który jest zdefiniowany jako const char*

No to teraz wywołanie tej funkcji:

#include "rejestr.h"
//---------------------------------------------------------------------------
rejestr klucznik;
int main()
{
   klucznik.usun_klucz(HKEY_LOCAL_MACHINE,"SOFTWARE\\Rafal");
        return 0;
}
//---------------------------------------------------------------------------

No tak zniszczyć to każdy umie,więc funkcja dodająca klucz do rejestru:

//------------------------------------------------------------------------------
//funkcja utworz_klucz wymaga prawa do tworzenia podkluczy w danym kluczu
//KEY_CREATE_SUB_KEY
//tworzy klucz wraz z kluczami nadrzędnymi gdy ich nie ma

void rejestr::utworz_klucz(HKEY   uchwyt_klucza_nadrzednego, 
                                                             //moze to byc któryś z
                                                             //kluczy głównych
                                                             //predefiniowanych
                                                             //lub uchwyt do klucza
                                                             //już otwartego
                           LPCTSTR nazwa_tworzonego_podklucza,
                           REGSAM     prawa_dostepu_do_klucza)
                                                         //REGSAM=unsigned long
{
  HKEY                 uchwyt_tworzonego_podklucza;
  DWORD                utworzono_otwarto_klucz;

  if (RegCreateKeyEx(uchwyt_klucza_nadrzednego,
                    nazwa_tworzonego_podklucza,
                                             0,     //zarezerwowane musi być 0
                                          NULL,     //Pointer to a null-terminated
                                                    //string that specifies the
                                                    //class (object type) of this
                                                    //key nie używam i nie wiem
                                                    //do czego jest,o jaką klasę
                                                    //chodzi
                       REG_OPTION_NON_VOLATILE,     //ta wartosc pozwala na
                                                    //utworzenie klucza nieulotnego
                                                    //czyli takiego,który zostanie
                                                    //zachowany po restarcie
                                                    //komputera,można użyć wartosci
                                                    //REG_OPTION_VOLATILE by
                                                    //utworzyć ulotny klucz
                       prawa_dostepu_do_klucza,
                                          NULL,     //wsk do struktury
                                                    //SECURITY_ATTRIBUTES
                                                    //określającej min czy
                                                    //zwracany uchwyt może
                                                    //być dziedziczony przez
                                                    //procesy potomne
                                                    //(child processes)
                                                    //zawiera także tzw
                                                    //deskrypror ochrony
                                                    //(SecurityDescriptor)
                                                    //który określa min
                                                    //właściciela obiektu
                                                    //nie -używam(wartość
                                                    //NULL) więc tej strukturce
                                                    //przydzielone wartosci
                                                    //domyślne
                  &uchwyt_tworzonego_podklucza,     //zwracany uchwyt podklucza
                  &utworzono_otwarto_klucz          //gdy wartość tej zmiennej
                                                    //wynosi REG_CREATED_NEW_KEY
                                                    //oznacza,że utworzono nowy
                                                    //klucz, natomiast gdy
                                                    //REG_OPENED_EXISTING_KEY
                                                    //oznacz otwarcie istniejącego
                                       )== ERROR_SUCCESS)
     {
       if(utworzono_otwarto_klucz==REG_CREATED_NEW_KEY)
         cout << "Utworzono klucz\n\n";
       else if(utworzono_otwarto_klucz==REG_OPENED_EXISTING_KEY)
         cout << "Podany klucz juz istnieje\n\n";
       RegCloseKey(uchwyt_tworzonego_podklucza);
     }
  else
    {
      cout << "\nUtworzenie klucza sie nie powiodlo, najprawdopodobniej\nnie  ";
      cout << "masz odpowiednich praw.";
    }
  cin.get();
}
//------------------------------------------------------------------------------

Oprócz dwóch parametrów jak w poprzedniej funkcji występuje trzeci
prawa_dostepu_do_klucza dzięki któremu możesz utworzyć klucz z takimi prawami jak chcesz,o ile system operacyjny ci na to pozwoli.Funkcja RegCreateKeyEx() tworzy klucz lub jeśli takowy istnieje otwiera. w obydwu tych przypadkach zwraca ERROR_SUCCESS.Ważne jest to,że po otwarciu lub utworzeniu klucza należy go zamknąć(zwrócić uchwyt).Robi to funkcja RegCloseKey().No to teraz wywołanie funkcji:

#include "rejestr.h"
//---------------------------------------------------------------------------
rejestr klucznik;
int main()
{
   klucznik.utworz_klucz(HKEY_LOCAL_MACHINE,
                                 "SOFTWARE\\Rafal\\rafal3\\r3",
                          KEY_ALL_ACCESS);
        return 0;
}
//---------------------------------------------------------------------------

aha w "scieżkach do klucza", tak to nazwijmy należy znak\ wypisywać jako \ czyli zgodnie z regółami języka c.

Kolejna funkcja składowa to funkcja usuń wartość,usuwać jest rzeczywiście prościej o czym się przekonamy.

//------------------------------------------------------------------------------
//funkcja wymaga prawa ustawiania(kasowania) wartości w podkluczu w którym
//chcemy ją skasować
//KEY_SET_VALUE

void rejestr::usun_wartosc(HKEY        uchwyt_klucza_nadrzednego,
                           LPCTSTR               nazwa_podklucza,
                           LPCTSTR                nazwa_wartosci)
{
  HKEY    uchwyt_podklucza;

  if(RegOpenKeyEx(uchwyt_klucza_nadrzednego,
                            nazwa_podklucza,
                  0,                                //wartość zarezerwowana
                                                    //musi być 0
                  KEY_SET_VALUE,                    //prawa dostępu do klucza
                  &uchwyt_podklucza)==ERROR_SUCCESS)   //tu zostanie zapisany
                                                       //uchwyt_podklucza
    {
      if( RegDeleteValue(uchwyt_podklucza,
                                nazwa_wartosci)==ERROR_SUCCESS )
          cout <<"\nWartosc zostala skasowana";
      else
        {
          cout << "Operacja nieudana, albo podana wartosc nie istnieje,\n\n";
          cout << "albo nie masz odpowiednich praw by ja skasowac. ";
        }
      RegCloseKey(uchwyt_podklucza);
    }
  else
    {
      cout << "Operacja nieudana, albo podana wartosc nie istnieje,\n\n";
      cout << "albo nie masz odpowiednich praw by ja skasowac. ";
    }
  cin.get();
}
//------------------------------------------------------------------------------

Ta funkcja również nie jest skomplikowana,najpierw musimy otworzyć klucz z którego chcemy skasować wartość z odpowiednimi prawami dostępu, jeśli to się powiedzie Funkcja RegOpenKeyEx zwróci ERROR_SUCCESS,a w ostatnim parametrze zapisze uchwyt do otworzonego klucza.W tym momęcie możemy skasować wartość i zamknąć klucz,ponieważ mamy uchwyt do tego klucza.
Tradycyjnie wywołanie funkcji:

#include "rejestr.h"
//---------------------------------------------------------------------------
rejestr klucznik;
int main()
{
   klucznik.usun_wartosc(HKEY_LOCAL_MACHINE,"SOFTWARE\\Rafal","New Value #5");
        return 0;
}
//---------------------------------------------------------------------------

Teraz omówie funkcje dodaj_wartość. Jak już mówiłem jest to funkcja o przeładowanej nazwie.Zdefiniowanych jest 5 funkcji o tej samej nazwie każda dodaje wartość innego typu do rejestru. Pierwsze trzy parametry tych funkcji są takie same,uchwyt_klucza nadrzędnego -podobnie jak poprzednio może to być uchwyt klucza głównego lub uchwyt klucza już otwartego. Dwa pozostałe parametry to nazwa_podklucza i nazwa wartości, chba nic nie trzeba wyjaśniać.W kolejnych parametrach przekazywane wartości które mają być utworzone w rejestrze.Omówię je przy poszczególnych funkcjach.No to do dzieła.

Funkcja dodająca do rejestru wartość DWORD-kod:

//------------------------------------------------------------------------------
//jeżeli istnieje wartość o tej same nazwie zostanie ona nadpisana
void rejestr::dodaj_wartosc(HKEY        uchwyt_klucza_nadrzednego,
                            LPCTSTR               nazwa_podklucza,
                            LPCTSTR                nazwa_wartosci,
                            DWORD                    wartosc_DWORD) //funkcja
                            //skladowa przeładowana-dodaje wartość DWORD

{
  HKEY    uchwyt_podklucza;

  if(RegOpenKeyEx(uchwyt_klucza_nadrzednego,
                            nazwa_podklucza,
                  0,                                //wartość zarezerwowana
                                                    //musi być 0
                  KEY_SET_VALUE,                    //prawa dostępu do klucza
                  &uchwyt_podklucza)==ERROR_SUCCESS)   //tu zostanie zapisany
    {                                                   //uchwyt_podklucza
      if(  RegSetValueEx(uchwyt_podklucza      ,
                         nazwa_wartosci        ,
                         0                     ,        //zarezerwowane musi być 0
                         REG_DWORD             ,        //typ danych
                         (BYTE*)&wartosc_DWORD ,        //dane
                         4                              //gdyby był niewłaściwy
                                                        //rozmiar wartość
                                                        //zostałaby utworzona
                                                        //ale byłaby
                                                        //nieprawidłowa
                          )== ERROR_SUCCESS    )
         {
           cout << "Wartosc zostala utworzona";
         }
      else
        {
          cout << "Operacja nieudana, albo klucz nie istnieje,\n\n" ;
          cout << "albo nie masz odpowiednich praw aby w nim utworzyc wartosc";
        }
      RegCloseKey(uchwyt_podklucza);
    }
  else
    {
      cout << "Operacja nieudana, albo klucz nie istnieje,\n\n" ;
      cout << "albo nie masz odpowiednich praw aby w nim utworzyc wartosc";
    }
  cin.get();

}
//------------------------------------------------------------------------------

Ostatnim parametrze tej funkcji jest typ DWORD=unsigned long tutaj właśnie przekazywana jest ta 32-bitowa liczba. Co się dzieje wewnątrz funkcji. Najpierw funcja RegOpenKeyEx() musi otworzyć podklucz z prawami dostępu pozwalającymi na doawanie w nim wartości. Uchwyt zwrócony przez tą funkcje wykorzystywany jest przez funkcje RegSetValueEx() aby wieiedzieć, w którym kluczu utworzyć wartość. Funkcja ta jest wywoływana z parametrem REG_DWORD określającym typ tworzonej wartości. W kolejnym parametrze wymagany jest wskażnik BYTE* wskazujący na komórki w pamięci zawierające wartość,a ponieważ wartość przekazywana jest do funkcji jako zmienna DWORD,więc uzyskujemy wskaźnik przy pomocy operatora adresu i rzutujemy ten wskaźnik na BYTE* i już..Następnym parametrem jest rozmiar wartości w Bajtach, musi być on 4 co wynika z definicji typu DWORD. Później tradycyjnie należy zamknąć klucz.
Wywołanie funkcji:

#include "rejestr.h"
//---------------------------------------------------------------------------
rejestr klucznik;
int main()
{
   klucznik.dodaj_wartosc(HKEY_LOCAL_MACHINE,"SOFTWARE\\Rafal",
                                         "wartosc_REG_DWORD",164);
        return 0;
}
//---------------------------------------------------------------------------

Funkcja dodająca do rejestru wartość REG_SZ-kod:

//------------------------------------------------------------------------------
void rejestr::dodaj_wartosc(HKEY        uchwyt_klucza_nadrzednego,
                            LPCTSTR               nazwa_podklucza,
                            LPCTSTR                nazwa_wartosci,
                            char                     * wartosc_SZ)
{
  HKEY    uchwyt_podklucza;

  if(RegOpenKeyEx(uchwyt_klucza_nadrzednego,
                            nazwa_podklucza,
                  0,                                //wartość zarezerwowana
                                                    //musi być 0
                  KEY_SET_VALUE,                    //prawa dostępu do klucza
                  &uchwyt_podklucza)==ERROR_SUCCESS)   //tu zostanie zapisany
    {                                                   //uchwyt_podklucza
      if(  RegSetValueEx(uchwyt_podklucza      ,
                         nazwa_wartosci        ,
                         0                     ,        //zarezerwowane musi być 0
                         REG_SZ                ,        //typ wartosci
                         wartosc_SZ            ,        //wartośc typu REG_SZ
                         strlen(wartosc_SZ)+1           //ten +1 na znak'\0'
                          )== ERROR_SUCCESS    )
           cout << "Wartosc zostala utworzona";
      else
        {
          cout << "Operacja nieudana, albo klucz nie istnieje,\n\n" ;
          cout << "albo nie masz odpowiednich praw aby w nim utworzyc wartosc";
        }
      RegCloseKey(uchwyt_podklucza);
    }
  else
    {
      cout << "Operacja nieudana, albo klucz nie istnieje,\n\n" ;
      cout << "albo nie masz odpowiednich praw aby w nim utworzyc wartosc";
    }
  cin.get();
}
//------------------------------------------------------------------------------

Funkcja jest bardzo podobna do poprzedniej,podam więc tylko różnice,
czwartym parametrem jest char* nie trzeba więc nawet dokonywać rzutowania w wywołaniu funkcji RegSetValueEx() bo BYTE jest zdefiniowany jako unsigned char. Typem wartości jest REG_SZ,natomiast długość pola w którym przechowywana jest wartość równa jest długości ciągu znaków + znak pusty.
No to wywołanie funkcji:

#include "rejestr.h"
//---------------------------------------------------------------------------
rejestr klucznik;
int main()
{
   klucznik.dodaj_wartosc(HKEY_LOCAL_MACHINE,"SOFTWARE\\Rafal",
                                  "wartosc_REG_SZ","ala ma kota");
        return 0;
}
//---------------------------------------------------------------------------

Funkcja dodająca do rejestru wartość REG_EXPAND_SZ-kod:

//------------------------------------------------------------------------------
void rejestr::dodaj_wartosc(HKEY        uchwyt_klucza_nadrzednego,
                            LPCTSTR               nazwa_podklucza,
                            LPCTSTR                nazwa_wartosci,
                            char                  * wartosc_EX_SZ,
                            int                  dla_rozroznienia) //nie używana
{
  HKEY    uchwyt_podklucza;

  if(RegOpenKeyEx(uchwyt_klucza_nadrzednego,
                            nazwa_podklucza,
                  0,                                //wartość zarezerwowana
                                                    //musi być 0
                  KEY_SET_VALUE,                    //prawa dostępu do klucza
                  &uchwyt_podklucza)==ERROR_SUCCESS)   //tu zostanie zapisany
    {                                                   //uchwyt_podklucza
      if(  RegSetValueEx(uchwyt_podklucza         ,
                         nazwa_wartosci           ,
                         0                        ,  //zarezerwowane musi być 0
                         REG_EXPAND_SZ            ,  //typ wartości
                         wartosc_EX_SZ            ,  //wartość tyou REG_EXPAND_SZ
                         strlen(wartosc_EX_SZ)+1     //ten +1 na znak'\0'
                          )== ERROR_SUCCESS    )
           cout << "Wartosc zostala utworzona";
      else
        {
          cout << "Operacja nieudana, albo klucz nie istnieje,\n\n" ;
          cout << "albo nie masz odpowiednich praw aby w nim utworzyc wartosc";
        }
      RegCloseKey(uchwyt_podklucza);
    }
  else
    {
      cout << "Operacja nieudana, albo klucz nie istnieje,\n\n" ;
      cout << "albo nie masz odpowiednich praw aby w nim utworzyc wartosc";
    }
  cin.get();
}
//------------------------------------------------------------------------------

Widzimy, że kod jest identyczny,róznica jest tylko w typie wartości RegSetValueEx() oraz dodatkowym 5-tym parametrze funkcji przeładowywanej w celu rozróżnienia.No więc wywołanie funkcji:

#include "rejestr.h"
//---------------------------------------------------------------------------
rejestr klucznik;
int main()
{
   klucznik.dodaj_wartosc(HKEY_CLASSES_ROOT,"batfile\\shell\\edit\\command",
                                  "","%SystemRoot%\\System32\\NOTEPAD.EXE %1",0);
        return 0;
}
//---------------------------------------------------------------------------

Tutaj dodawana jest wartość domyślna.

Funkcja dodająca do rejestru wartość REG_MULTI_SZ-kod:

//------------------------------------------------------------------------------
void rejestr::dodaj_wartosc(HKEY        uchwyt_klucza_nadrzednego,
                            LPCTSTR               nazwa_podklucza,
                            LPCTSTR                nazwa_wartosci,
                            char                 ** wartosc_ML_SZ)
{
  HKEY    uchwyt_podklucza;

  if(RegOpenKeyEx(uchwyt_klucza_nadrzednego,
                            nazwa_podklucza,
                  0,                                //wartość zarezerwowana
                                                    //musi być 0
                  KEY_SET_VALUE,                    //prawa dostępu do klucza
                  &uchwyt_podklucza)==ERROR_SUCCESS)   //tu zostanie zapisany
    {                                                   //uchwyt_podklucza
      int pierwsze_zero=0,
          dlugosc=0            ,
          drugie_zero=0   ;
          //znajdywanie długości multistringa
          while(!drugie_zero)
            {
              if( *(*wartosc_ML_SZ+dlugosc++)==0 )
                 if(pierwsze_zero)
                   drugie_zero=1;
                 else
                   pierwsze_zero=1;
              else
                pierwsze_zero=0;
            }
      if(  RegSetValueEx(uchwyt_podklucza         ,
                         nazwa_wartosci           ,
                         0                        ,  //zarezerwowane musi być 0
                         REG_MULTI_SZ             ,  //typ wartości
                         *wartosc_ML_SZ           ,  //wartość tyou REG_MULTI_SZ
                         dlugosc
                          )== ERROR_SUCCESS    )
           cout << "Wartosc zostala utworzona";
      else
        {
          cout << "Operacja nieudana, albo klucz nie istnieje,\n\n" ;
          cout << "albo nie masz odpowiednich praw aby w nim utworzyc wartosc";
        }
      RegCloseKey(uchwyt_podklucza);
    }
  else
    {
      cout << "Operacja nieudana, albo klucz nie istnieje,\n\n" ;
      cout << "albo nie masz odpowiednich praw aby w nim utworzyc wartosc";
    }
  cin.get();
}
//------------------------------------------------------------------------------

Szklelet tej funkcji jest identyczny jak poprzednich czyli : otwarcie klucza ,ustawienie wartości zamknięcie klucza. Parametrem w którym przekazywana jest wartość jest char **. Jest to zrobione w ten sposób ,aby możliwe było przekazanie do funkcji multistringu czyli tablicy stringów zakończonych znakiem pustym czyli tablicy wskaźników na char, a ponieważ nazwa tablicy jest nieruchomym wskaźnikiem , stąd wskaźnik do wskaźnika jest typem parametru. Jeżeli mamy dane w
takiej postaci to stosując operacje pojedynczego wyłuskiwania otrzymamy wskaźnik na char czyli wkażnik na BYTE a taki typ danych jest wymagany ,więc ok.Jedyne co nam jeszcze ppotrzeba to znaleźienie długości multistringu i to robi pętla while. Wyszukuje ona dwa znaki puste. Komentarza wymaga jeszcze ten zapis:
*(*wartosc_ML_SZ+dlugosc++)==0 -wyłuskiwanie z wartosc_ML_SZ powoduje, że dodając liczby nie poruszamy się po elementach tablicy czyli stringach tylko za każdym razem po jednym znaku,operator postinkrementacj powoduje, że poruszamy się od elementu 0. Drugi operator wyłuskiwania powoduje wyciągnięcie odpowiednik znaków, które następnie są porównane z 0 czyli '\0'. Pętla while kończy się gdy znajdziemy dwa takie znaki pod rząd i wtedy w zmiennej długosc jest długość multistringu.
Wywołanie funkcji:

#include "rejestr.h"
//---------------------------------------------------------------------------
rejestr klucznik;
int main()
{
   char *multistring[]={ "ACPI\\AuthenticAMD_-_x86_Family_6_Model_6",
                         "*AuthenticAMD_-_x86_Family_6_Model_6"     ,
                         "ACPI\\AuthenticAMD_-_x86_Family_6"        ,
                         "*AuthenticAMD_-_x86_Family_6"             ,
                         "ACPI\\AuthenticAMD_-_x86"                 ,
                         "*AuthenticAMD_-_x86"                      ,
                         ""                        };//zero kończące multistring

   klucznik.dodaj_wartosc(HKEY_LOCAL_MACHINE,"SOFTWARE\\Rafal",
                                   "wartosc_ML_SZ",multistring);
        return 0;
}
//---------------------------------------------------------------------------

Tutaj widzimy w jaki sposób możemy stworzyć multistring,ważny jest ten pusty string kończący bo inaczej funkcja(pętla while) pójdzie nam w buraki i owszem stworzy nam jakiś multistring, ale na jego końcu będą śmieci.

No to już ostatni typ wartości dodawany do rejestu.

Funkcja dodająca do rejestru wartość REG_BIN-kod:

//------------------------------------------------------------------------------
void rejestr::dodaj_wartosc(HKEY        uchwyt_klucza_nadrzednego,
                            LPCTSTR               nazwa_podklucza,
                            LPCTSTR                nazwa_wartosci,
                            BYTE                    * wartosc_BIN,
                            int                      ilosc_bajtow)
{
  HKEY    uchwyt_podklucza;

  if(RegOpenKeyEx(uchwyt_klucza_nadrzednego,
                            nazwa_podklucza,
                  0,                                //wartość zarezerwowana
                                                    //musi być 0
                  KEY_SET_VALUE,                    //prawa dostępu do klucza
                  &uchwyt_podklucza)==ERROR_SUCCESS)   //tu zostanie zapisany
    {                                                   //uchwyt_podklucza
      if(  RegSetValueEx(uchwyt_podklucza      ,
                         nazwa_wartosci        ,
                         0                     ,        //zarezerwowane musi być 0
                         REG_BINARY            ,        //typ wartosci
                         wartosc_BIN           ,        //wartośc typu REG_BIN
                         ilosc_bajtow
                          )== ERROR_SUCCESS    )
           cout << "Wartosc zostala utworzona";
      else
        {
          cout << "Operacja nieudana, albo klucz nie istnieje,\n\n" ;
          cout << "albo nie masz odpowiednich praw aby w nim utworzyc wartosc";
        }
      RegCloseKey(uchwyt_podklucza);
    }
  else
    {
      cout << "Operacja nieudana, albo klucz nie istnieje,\n\n" ;
      cout << "albo nie masz odpowiednich praw aby w nim utworzyc wartosc";
    }
  cin.get();
}
//------------------------------------------------------------------------------

Tym razem musimy do funkcji dołożyć dwa dodatkowe parametry jeden jest wskaźnikem na BYTE ,abyśmy mogli przekazać wartość w postaci tablicy bajtów, a drugi to rozmiar tej tablicy bo tym razem funkcja nie byłaby w stanie go sobie sama wyliczyć. Reszta nie wymaga chyba tłumaczenia. Wywołanie funkcji:

#include "rejestr.h"
//---------------------------------------------------------------------------
rejestr klucznik;
int main()
{
     BYTE dane[]={
                 0x3f,  0x00,  0x00,  0x00,  0x00,  0x01,  0x00,  0x00,
                 0x01,  0x01,  0x00,  0x00,  0x19,  0x00,  0x00,  0x00,
                 0x01,  0x00,  0x00,  0x00,  0x02,  0x00,  0x00,  0x00,
                 0x03,  0x00,  0x00,  0x00,  0x04,  0x00,  0x00,  0x00,
                 0x05,  0x00,  0x00,  0x00,  0x06,  0x00,  0x00,  0x00,
                 0x07,  0x00,  0x00,  0x00,  0x08,  0x00,  0x00,  0x00,
                 0x09,  0x00,  0x00,  0x00,  0x0a,  0x00,  0x00,  0x00,
                 0x0b,  0x00,  0x00,  0x00,  0x0c,  0x00,  0x00,  0x00,
                 0x0d,  0x00,  0x00,  0x00,  0x0e,  0x00,  0x00,  0x00,
                 0x0f,  0x00,  0x00,  0x00,  0x10,  0x00,  0x00,  0x00,
                 0x11,  0x00,  0x00,  0x00,  0x12,  0x00,  0x00,  0x00,
                 0x13,  0x00,  0x00,  0x00,  0x14,  0x00,  0x00,  0x00,
                 0x15,  0x00,  0x00,  0x00,  0x16,  0x00,  0x00,  0x00,
                 0x17,  0x00,  0x00,  0x00,  0x1a,  0x00,  0x00,  0x00,
                 0x18,  0x00,  0x00,  0x00,  0x1b,  0x00,  0x00,  0x00,
                 0x1c,  0x00,  0x00,  0x00,  0x1d,  0x00,  0x00,  0x00,
                 0x1e,  0x00,  0x00,  0x00,  0x1f,  0x00,  0x00,  0x00,
                 0x20,  0x00,  0x00,  0x00,  0x23,  0x00,  0x00,  0x00,
                 0x24,  0x00,  0x00,  0x00,  0x25,  0x00,  0x00,  0x00,
                 0x26,  0x00,  0x00,  0x00,  0x27,  0x00,  0x00,  0x00,
                 0x28,  0x00,  0x00,  0x00,  0x29,  0x00,  0x00,  0x00,
                 0x2a,  0x00,  0x00,  0x00,  0x2b,  0x00,  0x00,  0x00,
                 0x2c,  0x00,  0x00,  0x00,  0x2d,  0x00,  0x00,  0x00,
                 0x2e,  0x00,  0x00,  0x00,  0x2f,  0x00,  0x00,  0x00,
                 0x30,  0x00,  0x00,  0x00,  0x31,  0x00,  0x00,  0x00,
                 0x32,  0x00,  0x00,  0x00,  0x33,  0x00,  0x00,  0x00,
                 0x34,  0x00,  0x00,  0x00,  0x35,  0x00,  0x00,  0x00,
                 0x36,  0x00,  0x00,  0x00,  0x37,  0x00,  0x00,  0x00,
                 0x38,  0x00,  0x00,  0x00,  0x39,  0x00,  0x00,  0x00,
                 0x3a,  0x00,  0x00,  0x00,  0x3b,  0x00,  0x00,  0x00,
                 0x3c,  0x00,  0x00,  0x00,  0x3d,  0x00,  0x00,  0x00,
                 0x3e,  0x00,  0x00,  0x00,  0x3f,  0x00,  0x00,  0x00,
                                                                     };

     klucznik.dodaj_wartosc(HKEY_LOCAL_MACHINE,"SOFTWARE\\Rafal",
                                   "wartosc_BIN",dane,sizeof(dane));

        return 0;
}
//---------------------------------------------------------------------------

W rejestrze została utworzona ta wartość jaką pokazywałem gdy mówiłem o wartościach binarnych. Rozmiar tablicy uzyskujemy przy pomocy operatora SizeOf().

No to pozostała na placu boju tylko jedna funkcja składowa. Za to najdłuższa, wydobywająca informacje z jakiegoś klucza. Oto jej kod:

//------------------------------------------------------------------------------
//funkcja info_o_kluczu wymaga prawa do odczytu klucza rejestru KEY_READ
//spowodowane jest to tym,że z takim prawem jest wywoływana funkcja
//RegOpenKeyEx()

void rejestr::info_o_kluczu(
                   HKEY     uchwyt_klucza_nadrzednego,  //moze to byc któryś z
                                                       //kluczy głównych
                                                       //predefiniowanych
                                                       //lub uchwyt do klucza
                                                       //już otwartego
                   LPCTSTR         nazwa_podklucza,    //LPCSTR=const char*
                   int      rodzaj_informacji,
                   int      gdzie_zapisac)
{
  char        * przedrostek;                    //używany do wyświetlenia nazwy
                                                // klucza
  FILE        * plik;                           //przy zapisie danych do pliku
  HKEY        uchwyt_podklucza;
  LPTSTR      wsk_do_bufora_klasy=NULL;         //nie używam
  DWORD       rozmiar_bufora_klasy=0;           //nie używam
  DWORD       liczba_podkluczy=0;               //DWORD=unsigned long
  DWORD       dlugosc_najdluzszego_podklucza;
  DWORD       najdluzsza_klasa_string=0;       //nie używam
  DWORD       liczba_wartosci_klucza;
  DWORD       dlugosc_najdluzszej_nazwy_wartosci;
  DWORD       dlugosc_najdluzszej_wartosci;
  DWORD       rozmiar_deskryptora_ochrony;
  FILETIME    czas_ostatniego_zapisu;           /*typedef struct _FILETIME
                                                   {
                                                    DWORD dwLowDateTime;
                                                    DWORD dwHighDateTime;
                                                    } FILETIME,*PFILETIME;*/

  TCHAR       bufor_nazwy_podklucza[MAX_DLUGOSC_KLUCZA]; //zawiera nazwe
                                                                                   // podklucza
                                                         // TCHAR=unsigned char
  DWORD       dlugosc_nazwy_podklucza;
  TCHAR       bufor_nazwy_wartosci[MAX_DLUGOSC_NAZWY_WARTOSCI]; //zawiera nazwe
                                                                //wartosci
  DWORD       dlugosc_nazwy_wartosci;

  DWORD       kod_typu_zmiennej;   //przechowuje kod typu zmiennej(np REG_BINARY)
  DWORD       blad_sukces,i;       //wykorzystywana do sprawdzenia czy
                                   //operacja się powiodła
  BYTE        bufor_wartosci[MAX_DLUGOSC_WARTOSCI];   //przechowuje wartosc
                                                      //BYTE=unsigned char
  DWORD        dlugosc_bufora_wartosci;

  char  *typ_wartosci;    //używana do wyswietlenia nazwy typu wartosci

  int znak;              //zmienne używane do wyświetlenia typu REG_MULTI_SZ
  int drugi_znak=0,       //1 gdy wystąpi drugi z rzędu znak'\0'
      pierwszy_znak=0;    //1 gdy wystąpi pierwsze '\0'

  if(RegOpenKeyEx(uchwyt_klucza_nadrzednego,
                            nazwa_podklucza,
                  0,                           //wartość zarezerwowana musi być 0
                  KEY_READ,                    //prawa dostępu do klucza
                  &uchwyt_podklucza)==ERROR_SUCCESS)   //tu zostanie zapisany
                                                        //uchwyt_podklucza
    {
  //gdy otwarcie klucza się powiodło funkcja zwraca ERROR_SUCCESS
  //potrzebujemy troche informacji o kluczu
    if(RegQueryInfoKey(uchwyt_podklucza      ,   //teraz traktowany jako klucz
                                                 //nadrzędny
       wsk_do_bufora_klasy                   ,   // Pointer to a buffer that
                                                 //receives the null-terminated
                                                 //class string of the key
                                                 //nie mam pojęcia o jakie stringi
                                                 //chodzi, ale tego nie używam
       &rozmiar_bufora_klasy                 ,   //wsk do zmiennej przechowującej
                                                 //rozmiar bufora wskazywanego
                                                 //przez wsk_do_bufora_klasy
       NULL                                  ,   //zarezerrwowane musi być NULL
       &liczba_podkluczy                     ,   //wsk do zm zawierającej liczbe
                                                 //podkluczy
       &dlugosc_najdluzszego_podklucza       ,   //wsk do zm zawierającej
                                                 //najdłuższą nazwę
                                                 //podklucza w znakach

       &najdluzsza_klasa_string              ,   // Pointer to a variable that
                                                 //receives the
                                                 // size the longest string
                                                 //specifying a subkey class
                                                 //nie wiem o jakią klase podkluczy
                                                 // chodzi

       &liczba_wartosci_klucza               ,   //wsk do zm  zawierającej liczbe
                                                 //wartosci klucza
       &dlugosc_najdluzszej_nazwy_wartosci   ,   //wsk do zm zawierajacej  
                                                                     //najdłuższą
                                                 //nazwe wartosci długość w znakach
       &dlugosc_najdluzszej_wartosci         ,   //wsk do zm zawierającej najdluższą
                                                 //wartość(value data) w bajtach
       &rozmiar_deskryptora_ochrony          ,   //wsk do zm zawierającej rozmiar
                                                 //w bajtach deskryptora ochrony
                                                 //(key's security descriptor)
       &czas_ostatniego_zapisu                   //wsk do struktury typu
                                                 //_FILETIME zawierającej
                                                 //czas ostatniego zapisu
                               )==ERROR_SUCCESS)
      //gdy pobranie informacji o kluczu się powiodło funkcja zwraca ERROR_SUCCESS
         {
           if( uchwyt_klucza_nadrzednego==HKEY_CLASSES_ROOT )
             przedrostek="HKEY_CLASSES_ROOT";
           else if( uchwyt_klucza_nadrzednego==HKEY_CURRENT_CONFIG )
             przedrostek="HKEY_CURRENT_CONFIG";
           else if( uchwyt_klucza_nadrzednego==HKEY_CURRENT_USER )
             przedrostek="HKEY_CURRENT_USER";
           else if( uchwyt_klucza_nadrzednego==HKEY_LOCAL_MACHINE )
             przedrostek="HKEY_LOCAL_MACHINE";
           else if( uchwyt_klucza_nadrzednego==HKEY_USERS )
             przedrostek="HKEY_USERS";
           else if( uchwyt_klucza_nadrzednego==HKEY_DYN_DATA ) //klucz występuje
             przedrostek="HKEY_DYN_DATA";                      //tylko w Me/98/95
           else
             przedrostek="...";

           if( gdzie_zapisac & 1 )  //wypisz na ekran
             {
               printf("Informacje dotycza klucza : \n%s\\%s\n\n",
                                            przedrostek,nazwa_podklucza);
             }
           if( gdzie_zapisac & 2 )  //zapisz do pliku
             {
               plik=fopen("c:\klucz.txt","w");
               fprintf(plik,"Informacje dotycza klucza : %s\\%s\n\n",
                                            przedrostek,nazwa_podklucza);
             }

           if(  rodzaj_informacji  &   4 )  //wyliczenie podkluczy
             if(liczba_podkluczy)           //czy są jakieś podklucze
               {
                 if( gdzie_zapisac & 1 )  //wypisz na ekran
                     printf("Liczba podkluczy  :  %d\n\n",liczba_podkluczy);
                 if( gdzie_zapisac & 2 )  //zapisz do pliku
                   fprintf(plik,"Liczba podkluczy  :  %d\n\n",liczba_podkluczy);

                 for(i=0;i<liczba_podkluczy;i++)
                  {
                    dlugosc_nazwy_podklucza=MAX_DLUGOSC_KLUCZA;    //ta linia jest
                                                      //konieczna bo mogłoby się
                                                      //zdarzyć,że przy kolejnym
                                                      //wywołaniu wywołanie funkcji
                                                      //nie zakończy się sukcesem
                                                      //bo zbyt mało miejsca
                    blad_sukces=RegEnumKeyEx(uchwyt_podklucza          ,
                                             i                         , //licznik
                                                                         //podkluczy
                                             bufor_nazwy_podklucza     , //wsk do
                                                          //bufora zawierającego
                                                          //nazwe podklucza
                                                          //LPTSTR=char*
                                             &dlugosc_nazwy_podklucza  ,
                                               //wsk do zm zawierającej rozmiar
                                               //bufora zawierającego nazwy
                                               //podkluczy w TCHAR
                                             NULL                      ,
                                                  //zarezerwowane musi być NULL
                                             NULL                      ,
                                                  // Pointer to a buffer that receives
                                                  //the null-terminated class string
                                                  //of the enumerated subkey
                                                  //nie używam może być NULL
                                                  //nie wiem o jaką klase chodzi
                                             NULL                      ,
                                                 //wsk do zm zawierający rozmiar
                                                 //powyższego bufora
                                                 //nie używam może być NULL
                                             &czas_ostatniego_zapisu );
                                                 //wsk do struktury typu _FILETIME
                                                 //zawierającej
                                                 //czas ostatniego zapisu

                    if( blad_sukces==ERROR_SUCCESS )//zapis pojedynczego klucza
                      {
                        if( gdzie_zapisac & 1 )  //wypisz na ekran
                          printf("Nr %4d Nazwa : %s\n",i+1,bufor_nazwy_podklucza);
                        if( gdzie_zapisac & 2 )  //zapisz do pliku
                          fprintf(plik,"Nr %4d Nazwa : %s\n",i+1,
                                                         bufor_nazwy_podklucza);

                      } //endif
                  }//end for
               }//endif

           if(  rodzaj_informacji  &   3 )//Wyliczenie nazw wartosci i/lub wartosci
              {
                if ( liczba_wartosci_klucza )
                  {
                    if( gdzie_zapisac & 1 )  //wypisz na ekran
                       printf("\nLiczba wartosci  :  %d\n\n",
                                                         liczba_wartosci_klucza);
                    if( gdzie_zapisac & 2 )  //zapisz do pliku
                       fprintf(plik,"Liczba wartosci  :  %d\n\n",
                                                       liczba_wartosci_klucza);
                  }
                for(i=0; i<liczba_wartosci_klucza;i++)
                  {
                    dlugosc_nazwy_wartosci=MAX_DLUGOSC_NAZWY_WARTOSCI; //ta linia
                                                        //jest konieczna bo
                                                       //mogłoby się zdarzyć,że
                                                       //przy kolejnym wywołaniu
                                                       //wywołanie funkcji nie
                                                       //zakończy się sukcesem
                                                       //bo zbyt mało miejsca
                    dlugosc_bufora_wartosci=MAX_DLUGOSC_WARTOSCI;

                    blad_sukces=RegEnumValue(uchwyt_podklucza        ,
                                             i                       ,
                                                              //licznik wartosci
                                             bufor_nazwy_wartosci    ,
                                                  //wsk do bufora zawierającego
                                                  //nazwe wartosci
                                                  //LPTSTR=char*
                                             &dlugosc_nazwy_wartosci ,
                                                       //wsk do zm zawierającej
                                                       //rozmiar bufora
                                                       //zawierającego nazwy
                                                       //wartosci w TCHAR
                                             NULL                    ,
                                                  //Zarezerwowane Musi być NULL
                                             &kod_typu_zmiennej      ,

                                             bufor_wartosci          ,
                                                  //LPBYTE=BYTE*=unsigned char*
                                                  //przechowuje nazwe wartosci
                                             &dlugosc_bufora_wartosci);
                    if( blad_sukces==ERROR_SUCCESS )
                      {
                        if(  rodzaj_informacji  &   2 )//czy wypisac nazwe wartosci
                          {
                            if( gdzie_zapisac & 1 )  //wypisz na ekran
                              printf("Nr %4d Nazwa : %s\n",i+1,
                                                          bufor_nazwy_wartosci);
                            if( gdzie_zapisac & 2 )  //zapisz do pliku
                              fprintf(plik,"Nr %4d Nazwa : %s\n",i+1,
                                                         bufor_nazwy_wartosci);
                           }
                        if(  rodzaj_informacji  &   1 ) //czy dopisać wartosci
                                                      //(na ekran lub do pliku)
                          {
                            switch(kod_typu_zmiennej)//potrzebne do wypisania typu
                              {
                                case REG_BINARY :
                                       typ_wartosci="REG_BINARY";
                                     break;
                                case REG_DWORD :
                                       typ_wartosci="REG_DWORD";
                                     break;
                                case REG_EXPAND_SZ :
                                       typ_wartosci="REG_EXPAND_SZ";
                                     break;
                                case REG_MULTI_SZ :
                                       typ_wartosci="REG_MULTI_SZ";
                                     break;
                                case REG_SZ :
                                       typ_wartosci="REG_SZ";
                                     break;

                              }
                            if( gdzie_zapisac & 1 )  //wypisz na ekran
                               printf("Typ Wartosci  :  %s\n",typ_wartosci);
                            if( gdzie_zapisac & 2 )  //zapisz do pliku
                               fprintf(plik,"Typ Wartosci  :  %s\n",typ_wartosci);
                            switch(kod_typu_zmiennej)
                              {
                                case REG_BINARY :
                                     unsigned int k,a,z; //zm używane w pętlach
                                     int tab[4];
                                     int dlugosc;
                                     dlugosc=dlugosc_bufora_wartosci+
                                                 (8-dlugosc_bufora_wartosci%8);

                                     if( gdzie_zapisac & 1 )  //wypisz na ekran
                                       printf("Wartosc  :");
                                     if( gdzie_zapisac & 2 )  //zapisz do pliku
                                       fprintf(plik,"Wartosc  :");

                                     for(k=0;k <= dlugosc ;k++)
                                       {
                                         if( !(k % 8) )
                                           {
                                             //wyswietlenie 4 pierwszych kolumn
                                             if(k<dlugosc)
                                               {
                                                if( gdzie_zapisac & 1 )//wypisz na
                                                  printf("\n");        //ekran
                                                if( gdzie_zapisac & 2 )//zapisz
                                                  fprintf(plik,"\n"); //do pliku
                                                z=k;
                                                for(a=0;a<4;a++)
                                                 {
                                                   tab[a]=z & 15;
                                                   z=z >> 4;
                                                 }
                                                for(a=3;a+1>0;a--)
                                                  {
                                                    if( gdzie_zapisac & 1 )
                                                      printf("%x",tab[a]);
                                                    if( gdzie_zapisac & 2 )
                                                      fprintf(plik,"%x",tab[a]);
                                                  }
                                               }
                                           }


                                         if( k < dlugosc_bufora_wartosci)
                                                       //wyswietlenie wartosci(hex)
                                           {
                                             int dane_binarne=
                                                        (char)bufor_wartosci[k] ,
                                                 dolny_polbajt=dane_binarne & 15,
                                                 gorny_polbajt=
                                                         (dane_binarne & 240)>>4;

                                                 if( gdzie_zapisac & 1 )
                                                              //wypisz na ekran
                                                   printf("%3x%x ",gorny_polbajt,
                                                                 dolny_polbajt );
                                                 if( gdzie_zapisac & 2 )
                                                              //zapisz do pliku
                                                   fprintf(plik,"%3x%x ",
                                                     gorny_polbajt,dolny_polbajt );
                                           }
                                         else
                                           {
                                             if( gdzie_zapisac & 1 )
                                                               //wypisz na ekran
                                               printf("     ");
                                             if( gdzie_zapisac & 2 )
                                                               //zapisz do pliku
                                               fprintf(plik,"     ");
                                            }
                                          if( (k%8)==7 ) //wyswietlenie wartosci
                                                         //znakowo ,znaki o kodach
                                                         //0-31(sterujące)
                                                         //wyswietlane jako '.'
                                            {
                                              int i;
                                              for(i=k-7;i<=k;i++)
                                                if(i<dlugosc_bufora_wartosci)
                                                  {
                                                    if( (char)bufor_wartosci[i] < 32)
                                                      {
                                                        if( gdzie_zapisac & 1 )
                                                              //wypisz na ekran
                                                          putchar(46);
                                                        if( gdzie_zapisac & 2 )
                                                             //zapisz do pliku
                                                          putc(46,plik);
                                                      }
                                                    else
                                                      {
                                                        if( gdzie_zapisac & 1 )
                                                             //wypisz na ekran
                                                          putchar((char)
                                                            bufor_wartosci[i] );
                                                        if( gdzie_zapisac & 2 )
                                                             //zapisz do pliku
                                                          putc((
                                                          char)bufor_wartosci[i],
                                                                         plik );
                                                      } //end else
                                                  }//end if

                                            }//end if (k%8)==7

                                       }//end for
                                     if( gdzie_zapisac & 1 )  //wypisz na ekran
                                       printf("\n");
                                     if( gdzie_zapisac & 2 )  //zapisz do pliku
                                       fprintf(plik,"\n");
                                  break;
                                case REG_DWORD  :
                                     if( gdzie_zapisac & 1 )  //wypisz na ekran
                                        printf("Wartosc  :\nHex :%8lx(Dec : %ld)\n",
                                                      *((DWORD*)bufor_wartosci),
                                                     *((DWORD*)bufor_wartosci));
                                     if( gdzie_zapisac & 2 )  //zapisz do pliku
                                        fprintf(plik,
                                           "Wartosc  :\nHex :%8lx(Dec : %ld)\n",
                                                      *((DWORD*)bufor_wartosci),
                                                     *((DWORD*)bufor_wartosci));
                                  break;
                                case REG_SZ : case REG_EXPAND_SZ :
                                     if( gdzie_zapisac & 1 )  //wypisz na ekran
                                       printf("Wartosc  :\n%s\n",
                                                         (char*)bufor_wartosci);
                                     if( gdzie_zapisac & 2 )  //zapisz do pliku
                                       fprintf(plik,"Wartosc  :\n%s\n",
                                                         (char*)bufor_wartosci);
                                  break;
                                case REG_MULTI_SZ :
                                     if( gdzie_zapisac & 1 )  //wypisz na ekran
                                       printf("Wartosc  :\n");
                                     if( gdzie_zapisac & 2 )  //zapisz do pliku
                                       fprintf(plik,"Wartosc  :\n");
                                     int j=0;        //do przesuwania wskaznika
                                     drugi_znak=0;
                                     while(!drugi_znak)
                                       {
                                         if( ( znak=*(char*)(bufor_wartosci+j))==0)
                                           if(pierwszy_znak)
                                              {
                                               drugi_znak=1;
                                               pierwszy_znak=0;
                                              }
                                           else
                                             {
                                               pierwszy_znak=1;
                                               if( gdzie_zapisac & 1 )
                                                              //wypisz na ekran
                                                 printf("\n");
                                               if( gdzie_zapisac & 2 )
                                                              //zapisz do pliku
                                                 fprintf(plik,"\n");
                                             }
                                         else
                                           {
                                             if( gdzie_zapisac & 1 )
                                                              //wypisz na ekran
                                               putchar(znak);
                                             if( gdzie_zapisac & 2 )
                                                              //zapisz do pliku
                                               putc(znak,plik);
                                             pierwszy_znak=0;
                                           }
                                         j++;
                                       } //end while
                                  break;
                              }  //end sw


                          }//endif czy dop. wart
                      }//endif RegEnumValue sukces
                  }//end for
              }//endif wylicz nazw wart


           if( gdzie_zapisac & 1 )   //wypisz na ekran
             cin.get();              //czekaj na klawisz
           if( gdzie_zapisac & 2 )   //zapis do pliku
             fclose(plik);

         }//endif RegQueryInfoKey
      blad_sukces=RegCloseKey(uchwyt_podklucza);
    // zwolnienie uchwytu(zamknięcie klucza)
    }
   else
    {
      printf("Operacja sie nie powiodla,moze nie masz uprawnien");
      cin.get();
    }
}

//------------------------------------------------------------------------------

Co ta funkcja potrafi?
Jest to funkcja która która zapisuje informacje o kluczu rejestru, albo do pliku albo wypisuje je na ekran, zależnie od parametru gdzie_zapisac. W wywołaniu funkcji musimy podać uchwyt_klucza_nadrzędnego i nazwe_podklucza(czyli standardowo). Ostatni parametr określa jakiego rodzaju dane chcemy o tym kluczu. Możliwe kombinacje możemy zaobserwować przeglądając dyrektywy #define. Gdy wybierzemy maxymalną ilość informacji to wypisane zostaną podklucze,nazwy wartości,typy wartości oraz same wartości klucza. Ponieważ ten artykuł i tak jest przydługawy i jest cimna nyc to powiem tylko pokrótce o funkcjach używanych tutaj(reszta w komentarzach funkcji)
Na początku musimy dostać uchwyt do odpowiedniego klucza więc go otwieramy-RegOpenKeyEx().Następnie musimy uzyskać troszku informacji o kluczu czyli ile ma podkluczy ile wartości- RegQueryInfoKey().Następnie wywołujemy funkcje wyliczające klucze i wartości-RegEnumKeyEx() i RegEnumValue(). Funkcje te posiadają jako drugi parametr licznik, który przy pierwszym wywołaniu powinien być 0 i potem przy każdym następnym powinien być inkrementowany. Za każdym pobieraniem wartości zapisywana jest w odpowiednich zmiennych sama wartość,jej typ oraz rozmiar bufora w którym jest zapisana. Znając rozmiar bufora i typ wartości wykorzystując rzutowanie nie mamy problemu z odczytem wartości. Podobnie jest z nazwami. Pozostaje kwestia wyświetlenia na ekranie/zapisu do pliku.

Wywołanie tej funkcji:

#include "rejestr.h"
//---------------------------------------------------------------------------
rejestr klucznik;
int main()
{

     klucznik.info_o_kluczu(HKEY_LOCAL_MACHINE,
                "SYSTEM\\CurrentControlSet\\Control\\GroupOrderList",
                podklucze_nazwy_wartosci_wartosci,
                wypisz_na_ekran);

        return 0;
}
//---------------------------------------------------------------------------

Opis funkcji dotyczących rejestru możesz znaleźć tu:
http://msdn.microsoft.com/library/en-us/sysinfo/base/registry_functions.asp

No to by było na tyle...

RafalS

10 komentarzy

Pomóżcie bo jest to mi bardzo potrzebne. Z góry dzięki! =) [email protected]

super ale musdze miec wytłumaczenie.Kto pomoże i dostarczy mi pełny plik rejestr i plik projektu jakis przykladowy z wykorzystaniem.Tak żebym mogl sobie usuwac edytowac i tworzyc klucze. Prosze o pomoc i wyrozumiałość!!!!

Jeszcze całości nie przeczytałem.... Ale przyda się. Masz u mnie solidne 5 :)

Hej ziomal znasz się na rzeczy.

tylko pogratulować :)

Wiesz jesli to naprawde twoj artykul to gratuluje ale nieczesto sie zdarza ze uzytkownik z tygodniowym starzem pisze tak obfite artykuly.

Co za 'he?' ?

Dobry artykul, mimo ze duza czesc zajmuja listingi, nie mam zastrzezen.

o w morde do końca wakacji nie zdąże chyba przeczytać :]