W tej lekcji przedstawię jak obsługiwać rejestr windowsa z poziomu aplikacji.

Krótko o rejestrze.

Mam nadzieje, że każdy choć po części wie czym jest rejestr w Windowsie. Trochę go trochę przybliżę. Rejestr w Windowsie to struktura danych, która ma na celu przede wszystkim służyć przechowywaniu różnych ustawień windowsa i innych programów. Technicznie rejestr na dysku rozbity jest na kilka plików. Aby edytować rejestr w poleceniu uruchom w menu start należy wpisać: "regedit". Jest to poprsotu systemowy program do edycji rejestru, powinien on wyglądać mniej więcej tak:

Przyjrzyjmy się teraz strukturze rejestru. Odrazu mówię, ze w różnych wydaniach Windowsa, struktura rejestru może wyglądać trochę inaczej, warto więc zwrócić na to uwagę, gdy chcemy pisać program, który ma działać pod różnymi Windowsami. Na pierwszy rzut oka, widzimy, że rejestr windowsa XP składa się z 5 głównych kluczy. Nie będę tutaj omawiał danych kluczów, bo to nie jest celem tej lekcji. Te 5 głównych kluczy rozkłada się na ogromne gałęzie kluczy, a w każdym kluczu mogą być zapisane różne wartości, dla przykładu sprawdźmy jakie wartości są w kluczu: "HKEY_LOCAL_MACHINESOFTWAREDev-C++". Widzimy, że w tym kluczu, jest jedna wartość(oprócz domyślnej, która jest w każdym kluczu) o nazwie "Install_Dir". Można się domyślić, że jest to ustawienie naszego kompilatora, a konkretniej, ścieżka na jakiej został on zainstalowany.

Do czego może nam się przydać rejestr?

Jak już wspomniałem, rejestr ma przechowywać konfiguracje i do tego go będziemy wykorzystywać w naszym programie. Widzieliśmy, że program Dev C++, zapisał w rejestrze swoją ścieżkę. My także możemy pisać programy, które będą mogły zapisaywać swoje ustawienia czy jakieś inne dane do rejestru.

OBSŁUGA REJESTRU

1. Otwarcie klucza - RegOpenKeyEx

Funkcje obsługujące rejestr znajdują się w pliku nagłówkowym o nazwie "winreg.h", jest on także dodany w windows.h.

Swoją pracę z rejestrem zaczynamy od utworzenia uchwytu na klucz (HKEY).

#include <windows.h>

INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR lStart,INT nShow)
{
  HKEY klucz;
//deklarujemy uchwyt na klucz o nazwie "klucz"

  return
0
;
}

Mając uchwyt, możemy otworzyć jakiś istniejący klucz, bądź stworzyć całkiem nowy.

Istniejący klucz otwieramy funkcją RegOpenKeyEx, oto jej deklaracja:

LONG RegOpenKeyEx(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, REGSAM samAccess ,PHKEY phkResult);

HKEY hKey
Tutaj zwykle podajemy identyfikator do głównego klucza w rejestrze, czyli jeden z 4 głównych kluczy:
HKEY_CLASSES_ROOT
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
Możemy także podać uchwyt jeden z wcześniej otwartych kluczy, pod warunkiem, że ten klucz jest wyżej w hierarhii kluczy, niż ten który chcemy otworzyć.

LPCSTR lpSubKey
Nazwa otwieranego klucza w formie ścieżki do niego, np.: "SOFTWARE\Dev-C++". Ścieżka ta powinna się zaczynać do klucza o jednego niżej w hierarhii kluczy.

DWORD Reserved
Ta wartość jest zarezerwowana i powinniśmy podać tu poprsotu 0.

REGSAM samAccess
Sposób otwarcia klucza. Na temat dostępu do klucza jest trochę niżej.

PHKEY
Wskaźnik na uchwyt zmiennej, do której zostanie zwrcóny uchwyt z nowo otwartym kluczem. W większości funkcji utworzony uchwyt, zostaje zwrócony przez funkcję, tutaj natomiast widzimy, że uchwyt zostanie umieszczony w zmiennej podanej w parametrach.

Wartość zawacana przez funkcję
Jeżeli podany klucz, będzie istniał i uda się go otworzyć, to funkcja zwróci wartość ERROR_SUCCESS. Jeżeli klucza nie uda się otworzyć, funkcja zwróci numer błędu.

/*Przykład użycia funkcji RegOpenKeyEx
Otwierany klucz:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
*/

#include <windows.h>

INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR lStart,INT nShow)
{
  HKEY klucz;
//uchwyt do otwieranego klucza

  LONG Wynik;
//wynik funkcji RegOpenKeyEx

  Wynik=RegOpenKeyEx(HKEY_CURRENT_USER,
"Software\\Microsoft\\Windows\\CurrentVersion\\Run"
,
0
,KEY_ALL_ACCESS,
  &klucz);
  if(Wynik==ERROR_SUCCESS)
  {
    MessageBox(HWND_DESKTOP,
"Klucz został otwarty"
,
"Sukces"
, MB_OK);
    RegCloseKey(klucz);
//zamkniecie klucza - o tym dalej

  }
  else MessageBox(HWND_DESKTOP,
"Klucz nie został otwarty"
,
"Błąd"
,MB_OK);
  return
0
;
}

2. Utworzenie lub otwarcie klucza - RegCreateKeyEx

Funkcja RegCreateKeyEx jest bardziej elastyczna niż, RegOpenKeyEx, ponieważ jeżeli podany klucz istnieje to otwiera go, tak jak funkcja RegOpenKeyEx, natomiast jeżeli klucz nie istnieje tworzy go.
Oto jej prototyp:

LONG RegCreateKeyEx(HKEY hKey,LPCSTR lpSubKey,DWORD Reserved,LPSTR lpClass,DWORD dwOptions,REGSAM samAccess,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,PHKEY phkResult,PDWORD lpdwDisposition);

HKEY hKey
Tak samo, jak w poprzedniej funkcji, podajemy identyfikator do głównego klucza w rejestrze.

LPCTSTR lpSubKey
Tak samo, jak w poprzedniej funkcji, podajemy nazwę otwieranego klucza w formie ścieżki do niego.

DWORD Reserved
Ta wartość jest zarezerwowana, jak to miało miejsce w przypadku poprzedniej funkcji.

LPSTR lpClass
Jest to typ klucza, Microsoft podaje, że można go ignorować, tak też zrobimy, podając tu zawsze 0.

DWORD dwOptions
Parametr ten decyduje, czy klucz ma być zapisany na dysk, czy tylko do pamięci, a po ponownym uruchomieniu kompa zniknie.
Mamy tu do możliwości dwie podstawowe flagi:
REG_OPTION_NON_VOLATILE - klucz zostanie zapisany do rejestru na dysku, wstawiając go na stałe do rejestru.
REG_OPTION_VOLATILE - klucz zostanie zapisany do rejestru załadowanego do pamięci, a po ponownym uruchomieniu komputera klucza juz nie będzie.

REGSAM samAccess
Sposób otwarcia klucza. Na temat dostępu do klucza jest trochę niżej.

LPSECURITY_ATTRIBUTES lpSecurityAttributes
Wskaźnik do struktury atrybutów ochrony, dostępnej dopiero od Windows 2000. Ja proponuję dać tutaj 0 i nie bawić się z takimi rzeczami.

PHKEY
Tak jak w przypadku poprzedniej funkcji jest to wskaźnik na uchwyt zmiennej, do której zostanie zwrcóny uchwyt z nowo utworzony kluczem.

PDWORD lpdwDisposition
Jest wskaźnik do zmiennej, w której zostanie umieszczona informacja, o tym czy został utworzony nowy klucz lub czy został otworzony już istniejący.
Jezeli wartość tej zmiennej będzie wynosiła:
REG_CREATED_NEW_KEY - znaczy, że został utworzony nowy klucz
REG_OPENED_EXISTING_KEY - oznacza, że został otwarty juz istniejący klucz.

Wartość zawacana przez funkcję
Jeżeli podany klucz, będzie istniał i uda się go otworzyć, to funkcja zwróci wartość ERROR_SUCCESS. Jeżeli klucza nie uda się otworzyć, funkcja zwróci numer błędu.

/*Przykład użycia funkcji RegCreateKeyEx
Tworzony klucz:
HKEY_CURRENT_USER/Software/Nasz program
*/

#include <windows.h>

INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR lStart,INT nShow)
{
  HKEY klucz;
//uchwyt do tworzonego klucza

  LONG Wynik;
//wynik funkcji RegCreateKeyEx

  DWORD Nowy;
//wartość na sprawdzenie czy został utworzony nowy klucz

  Wynik=RegCreateKeyEx(HKEY_CURRENT_USER,
"Software\\Nasz program"
,
0
,
0
,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,   
0
,&klucz,&Nowy);
  if(Wynik==ERROR_SUCCESS)
  {
    MessageBox(HWND_DESKTOP,
"Funkcja wykonała się prawidłowo"
,
"Sukces"
,MB_OK);
    RegCloseKey(klucz);
//zamkniecie klucza - o tym dalej

    if(Nowy==REG_CREATED_NEW_KEY) MessageBox(
0
,
"Została utworzony nowy klucz"
,
"Nowy klucz"
,MB_OK);
    else MessageBox(HWND_DESKTOP,
"Został otwarty stary klucz"
,
"Stary klucz"
,MB_OK);
    return
0
;
  }
  else MessageBox(HWND_DESKTOP,
"Funkcja nie wykonała się prawidłowo"
,
"Błąd"
,MB_OK);
  return
0
;
}

3. Poziom dostępu klucza do wartości w nim.

Podczas otwierania klucza funkcjami, jeden parametr określaja spsób otwarcia klucza, oto jakie wartości możemy podać, podam tylko te najczęściej używane, które z pewnością wystarczą:
KEY_READ - wartości z otwartego klucza są tylko do odczytu, nie możemy nic w nim edytować.
KEY_WRITE - w otwartym kluczu, możemy edytować wartości, usuwać, dodawać, tworzyć kolejne klucze, ale nie możemy odczytywać wartości.
KEY_SET_VALUE - w otwarym kluczu możemy tylko edytować, dodawać i usuwać wartości.
KEY_ALL_ACCESS - otwarty klucz będzie miał wszystkie prawa dostępu

4. Zamknięcie klucza - RegCloseKeyEx

Kiedy otworzymy klucz(uzyskamy uchwyt do niego), po skończeniu pracy z nim, mamy obowiązek go zwolnić, zresztą jest to ogólna zasada do wszystkich obiektów w WinAPI, które tworzymy uzyskując ich uchwyty. Aby zwolnić klucz rejestru używamy funkcji RegCloseKeyEx. Nie jest to zbyt skomplikowana funkcja, bo ma tylko jeden parametr. Jest nim uchwyt do wcześniej otworzonego/stworzonego klucza. W przykładach poprzednich programów widać zastosowanie tej funkcji.

LONG RegCloseKey(HKEY hKey);

HKEY hKey
Uchwyt do zwalnianego klucza.

Wartość zawacana przez funkcję
Jeżeli klucz zostanie zwolniony bez błędów, zostanie zwrócona wartość ERROR_SUCCES, w przeciwnym wypadku, dostaniemy numer błędu.

5. Usuwanie klucza - RegDeleteKey

Mamy także funckje usuwającą klucz w rejestrze Windowsa. UWAGA! Aby można było usunąć dany klucz, nie może on mieć żadnych podkluczy. Jej prototyp:

LONG RegDeleteKey(HKEY hKey,LPCSTR lpSubKey);

HKEY hKey
Standardowo identyfikator do głównego klucza w rejestrze.

LPCSTR lpSubKey
Ścieżka do usuwanego klucza.

Wartość zawacana przez funkcję
Jeżeli klucz zostanie poprawnie usunięty, funkcja zwróci wartość ERROR_SUCCESS, w przecinwym wypadku zostanie zwrócony kod błędu.

6. Odczytywanie wartości z otwartego klucza - RegQueryValueEx

Czas na pracę z wartościami. Gdy otworzymy jakiś klucz, możemy odczytać jego wartości. Pamiętajmy, że aby móc odczytać wartość, klucz musi mieć uprawnienia odczytywania z niego wartości. Funkcja RegQueryValueEx słuzy do odczytywania jakiejś wartości w kluczu, jej prototyp:

LONG RegQueryValueEx(HKEY hKey,LPCSTR lpValueName,LPDWORD Reserved,LPDWORD lpType,LPBYTE lpData,
LPDWORD lpcbData);

HKEY hKey
Uchwyt do otwartego klucza.

LPCSTR lpValueName
Nazwa odczytywanej wartości w danym kluczu.

LPDWORD Reserved
Parametr zarezerwowany, podajemy tu 0.

LPDWORD lpType
Format danych jakie chcemy odczytać, o formatach będzie trochę niżej.

LPBYTE lpData
Jest to wskaźnik, na zmienną do której mają zostać odczytane dane. Wskaźnik zmiennej należy rzutaować na wskaźnik LPBYTE.

LPDWORD lpcbData
Jest to wskaźnik do zmiennej, w której zostanie umieszczona długość odczytanej wartości w bajtach. Jeśli nie potrzebny nam rozmiar zmiennej podajemy tu 0.

Wartość zawacana przez funkcję
Jeżeli wartość zostanie poprawnie odczytana, funkcja zwróci wartość ERROR_SUCCESS, w przecinwym wypadku zostanie zwrócony kod błędu.

Przykładowe użycie funkcji RegQueryValueEx:

/*Przykład użycia funkcji RegQueryValueEx
Otwierany klucz:
SOFTWARE\Microsoft\Windows\CurrentVersion
Nazwa odczytywanej wartości:
SM_AccessoriesName
*/

#include <windows.h>

INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR lStart,INT nShow)
{
  HKEY klucz;
//uchwyt do otwieranego klucza
  //otwarcie klucza funkcją RegOpenKeyEx

  if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion"
,
0
,KEY_READ,
  &klucz)!=ERROR_SUCCESS) MessageBox(
0
,
"Nie można otworzyć klucza"
,
"Błąd"
,MB_OK);
  CHAR wartosc[
256
];
//łańcuch znaków na odczytaną wartość

  DWORD rozmiar;
//rozmiar odczytanej wartości(w bajtach)

  DWORD typ_danych=REG_SZ;
//zmienna na typ danych
  //odczytanie wartości z klucza

  if(RegQueryValueEx(klucz,
"SM_AccessoriesName"
,
0
,&typ_danych,(LPBYTE)wartosc,&rozmiar)!=ERROR_SUCCESS)
  MessageBox(
0
,
"Nie można odczytać wartości"
,
"Błąd"
,MB_OK);
  
//pokazanie wyników

  MessageBox(
0
,wartosc,
"Odczytana wartość"
,MB_OK);
//pokazanie odczytanej wartosci

  CHAR wielkosc[
8
];
//łańcuch znaków na wielkość odczytanej wartosci

  itoa((INT)rozmiar,wielkosc,
10
);
//konwersja wartości z DWORD na tekst - funkcja C++

  MessageBox(
0
,wielkosc,
"Wilekość odczytanej wartości"
,MB_OK);
//wyświetlenie rozmiaru odczytanej wartości

  RegCloseKey(klucz);
//zamknięcie klucza

  return
0
;
}

7. Zapisywanie wartości w kluczu - RegSetValueEx

Teraz pora na zapis wartości, oczywiście otwarty klucz musi mieć dostęp do zapisu wartości. Działanie funkcji jest proste, zapisuje ona wartość o podanej nazwie, jeżeli wartość wcześniej istniała, to nadpisuje ją.

LONG RegSetValueEx(HKEY hKey,LPCSTR lpValueName,DWORD Reserved,DWORD dwType,CONST BYTE* lpData,DWORD cbData);

HKEY hKey
Uchwyt do otwartego klucza.

LPCSTR lpValueName
Nazwa zapisywanej wartości w danym kluczu.

DWORD Reserved
Po nazwie chyba wiadomo o co chodzi.

DWORD dwType
Format zapisywanych danych. O tym w następnym punkcie.

CONST BYTE* lpData
Wskaźnik do zmiennej, jaką chcemy zapisać.

DWORD cbData
Podajemy ile bajtów chcemy zapisać do wartości w rejestrze.

Wartość zawacana przez funkcję
Jeżeli wartość zostanie poprawnie zapisana, funkcja zwróci wartość ERROR_SUCCESS, w przecinwym wypadku zostanie zwrócony kod błędu.

Przykładowe uzycie funkcji RegSetValueEx:

/*Przykład użycia funkcji RegSetValueEx
Otwierany klucz:
HKEY_CURRENT_USER\Software
Nazwa tworzonej wartości:
Moja wartość
Tworzona wartość:
Coś co zapisujemy
*/

#include <windows.h>

INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR lStart,INT nShow)
{
  HKEY klucz;
//uchwyt do otwieranego klucza
  //otwarcie klucza funkcją RegOpenKeyEx

  if(RegOpenKeyEx(HKEY_CURRENT_USER,
"Software"
,
0
,KEY_WRITE,&klucz)!=ERROR_SUCCESS)
  MessageBox(
0
,
"Nie można otworzyć klucza"
,
"Błąd"
,MB_OK);
  CHAR wartosc[]=
"Coś co zapisujemy :>"
;
//łańcuch znaków z zapisywana wartością

  DWORD typ_danych=REG_SZ;
//typ wartości
  //zapisywanie wartości do klucza

  if(RegSetValueEx(klucz,
"Moja wartość"
,
0
,typ_danych,(LPBYTE)wartosc,sizeof(wartosc))!=ERROR_SUCCESS)
  MessageBox(
0
,
"Nie można zapisać wartości"
,
"Błąd"
,MB_OK);
  
//jeśli sie nie uda

  RegCloseKey(klucz);
//zamknięcie klucza

  return
0
;
}

8.Formaty wartości

Podczas zapisu i odczytu wartości musimy określić, jakiego typu są te wartości. Oto możliwe flagi:

REG_BINARY - dane binarne(ciąg zer i jedynek),
REG_DWORD - liczba 32bitowa,
REG_SZ - ciąg znaków(tekst), konczący sie znakiem końca tablicy(\0),
REG_MULTI_SZ - ciąg znaków, który kończy się z dopiero po dwóch kolejnych znakach końca tablicy(\0\0),
REG_NONE - nieokreślony typ danych.

9. Usuwanie wartości z klucza - RegDeleteValue

Funkcja RegDeleteValue usuwa wartość o podanej nazwie w danym kluczu. Jej deklaracja:

LONG RegDeleteValue(HKEY hKey, LPCSTR lpValueName);

HKEY hKey
Uchwyt do otwartego klucza.

LPCSTR lpValueName
Nazwa usuwanej wartości w danym kluczu.

Podstawowe funkcje do poruszania się po rejestrze znasz. Jeżeli chcesz dowiedzieć się czegoś więcej zachęcam do odwiedzenia MSDN: http://msdn2.microsoft.com/en-us/library/ms724871.aspx