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
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?' ?
he?
Dobry artykul, mimo ze duza czesc zajmuja listingi, nie mam zastrzezen.
o w morde do końca wakacji nie zdąże chyba przeczytać :]