Ładowanie
Angielski
Rosyjski
Strona domowa Mikołaja Hajduka

Prosty generator haseł

P
rogram SimPaGen jest prostym w obsłudze, niewielkim i bardzo elastycznym programem służącym do generowania haseł. Napisana w FASMie aplikacja użytkowa ułatwia proces tworzenia bezpiecznych haseł niezbędnych dla uzyskania dostępu do forów dyskusyjnych, skrzynek pocztowych i innych tego typu portali.

Oto prosta animacja prezentująca działanie programu SimPaGen:

Dane techniczne

Program generuje hasła złożone ze znaków należących do dowolnej kombinacji czterech podstawowych kategorii:

  • litery A, ..., Z,
  • litery a, ..., z,
  • cyfry 0, ..., 9,
  • znak podkreślenia '_'
oraz dowolnego zbioru znaków zdefiniowanego przez użytkownika. Ilość wszystkich możliwych do zdefiniowania niepustych zbiorów znaków składowych jest równa 2224-1 (ilość wszystkich niepustych podzbiorów zbioru znaków o szesnastkowych kodach od 0x20 do 0xFF). Maksymalna długość wygenerowanego hasła wynosi 9999 znaków. Utworzone hasło można skopiować do schowka przy pomocy przycisku

Ponadto, dzięki istnieniu skrótu klawiszowego WIN + F12, istnieje możliwość jednoczesnego wygenerowania nowego hasła i umieszczenia go w schowku, nawet w przypadku, gdy okno programu nie jest aktywne. Ustawienia programu dotyczące ilości znaków hasła oraz zbioru znaków składowych tworzonych haseł są zapisywane każdorazowo przed zakończeniem pracy aplikacji w kluczu rejestru

HKEY_CURRENT_USER\Software\SimPaGen\<wersja_programu>

Program wykorzystuje funkcje CryptoAPI biblioteki 'advapi32.dll', dzięki czemu uzyskany ciąg znaków hasła jest "kryptograficznie losowy".

Do pliku źródłowego programu włączono bezpośrednio treść manifestu, jak również dane ikon programu.

Program może być traktowany jako przykład subclassingu zastosowanego do pól tekstowych.

Historia projektu

v.2008.08.12.0 - pierwsza publicznie zaprezentowana wersja programu.

v.2008.09.11.0 - dodatki i zmiany:

  • dodano przycisk kopiujący do schowka treść hasła znajdującego się w polu tekstowym programu,
  • dodano skrót klawiszowy WIN + F12, którego naciśnięcie powoduje wygenerowanie nowego hasła i skopiowanie jego treści do schowka (skrót działa również wtedy, gdy okno programu jest nieaktywne),
  • dodano możliwość zapamiętywania bieżących ustawień programu (długość generowanego hasła oraz zestaw znaków składowych) w odpowiednim kluczu rejestru,
  • uproszczono i usprawniono operacje na tablicy definiującej funkcję charakterystyczną zbioru znaków składowych tworzonych haseł.

Źródło

Poniżej zaprezentowano treść pliku źródłowego programu:

; Program w FASMie służący do generowania haseł złożonych ze znaków należących
; do dowolnej kombinacji czterech predefiniowanych kategorii:
;
;	* litery A, ..., Z,
;	* litery a, ..., z,
;	* cyfry 0, ..., 9,
;	* znak podkreślenia '_'
;
; oraz dowolnego zbioru znaków zdefiniowanego przez użytkownika. Ilość wszystkich
; możliwych do zdefiniowania niepustych zbiorów znaków składowych jest równa
; 2^224-1 (ilość wszystkich niepustych podzbiorów zbioru znaków o szesnastkowych
; kodach od 0x20 do 0xFF). Maksymalna długość wygenerowanego hasła wynosi 9999
; znaków. Utworzone hasło można skopiować do schowka przy pomocy przycisku z ikoną.
;
; Ponadto, dzięki istnieniu skrótu klawiszowego WIN + F12, istnieje możliwość
; jednoczesnego wygenerowania nowego hasła i umieszczenia go w schowku, nawet
; w przypadku, gdy okno programu nie jest aktywne.
;
; Ustawienia programu dotyczące ilości znaków hasła oraz zbioru znaków składowych
; tworzonych haseł są zapisywane każdorazowo przed zakończeniem pracy aplikacji
; w kluczu rejestru
;
;		HKEY_CURRENT_USER\Software\SimPaGen\<wersja_programu>
;
; Program wykorzystuje funkcje CryptoAPI biblioteki 'advapi32.dll', dzięki czemu
; uzyskany ciąg znaków hasła jest "kryptograficznie losowy".
;
; Do pliku źródłowego programu włączono bezpośrednio treść manifestu, jak również
; dane ikon programu.
;
; Program może być traktowany jako przykład subclassingu zastosowanego do pól
; tekstowych.
;  
; (C) Mikołaj Hajduk, 11.09.2008.
;
; Strona domowa:	http://mikhajduk.houa.org
; E-mail:		mikhajduk@gmail.com
;
format PE GUI 4.0

; Wklejenie pliku zawierającego definicje wszystkich niezbędnych makr FASMa
; wykorzystanych w programie.
;
include 'win32wx.inc'

; Określenie zestawu znaków, użytego do zakodowania treści pliku źródłowego.
;
include '\ENCODING\utf8.inc'

; Stała przechowująca informację nt. aktualnej wersji programu.
;
PROG_VERSION	equ '2008.09.11.0'


; Definicje danych globalnych.
;
section '.data' data readable writeable

	; Łańcuchy znaków zawierające nazwy klas predefiniowanych w systemie Windows.
	;
	_edit		du 'EDIT', 0
	_button		du 'BUTTON', 0
	_static		du 'STATIC', 0

	; Łańcuchy znaków przechowujące nazwy definiowanych przez nas klas.
	;
	_MainClass	du 'SimPaGen', 0
	_PassPanelClass	du 'PassPanel', 0
	_CharPanelClass	du 'CharPanel', 0

	; Definicje używanych w programie klas okien.
	;
	MainClass	WNDCLASS 0, WindowProc, 0, 0, NULL, NULL, NULL, COLOR_BTNFACE + 1, NULL, _MainClass
	PassPanelClass	WNDCLASS 0, PassPanelProc, 0, 0, NULL, NULL, NULL, COLOR_BTNFACE + 1, NULL, _PassPanelClass
	CharPanelClass	WNDCLASS 0, CharPanelProc, 0, 0, NULL, NULL, NULL, COLOR_BTNFACE + 1, NULL, _CharPanelClass

	; Uchwyt czcionki używanej do wyświetlania napisów w kontrolkach.
	;
	Font		dd ?

	; Struktura przechowująca informacje nt. przetwarzanego komunikatu.
	;
	msg		MSG

	; Uchwyt modułu aplikacji.
	;
	hInstance	dd ?

	; Uchwyt panelu, w którym generujemy hasła.
	;
	PassPanel	dd ?

	; Uchwyt panelu, w którym definiowany jest zbiór znaków składowych
	; dla tworzonych haseł.
	;
	CharPanel	dd ?

	; Tablica definiująca funkcję charakterystyczną zbioru znaków składowych.
	;
	CharFun		rd 7

	; Tablica przechowująca łańcuchową reprezentację liczby określającej
	; długość tworzonych haseł.
	;
	PassLen		du '10'
			rb 6

	; Zmienna przechowująca zestaw flag informujących o stanie pól wyboru
	; odpowiadających standardowym kategoriom znaków.
	;
	Flags		dw 0


; Sekcja zawierająca kod wykonywalny programu.
;
section '.code' code readable writeable executable

	start:
		; Sprawdzenie, czy biblioteka 'comctl32.dll' jest załadowana.
		; Jest to konieczne, jeśli chcemy korzystać z pliku manifestu.
		;
		invoke	InitCommonControls

		; Pobranie uchwytu modułu aplikacji.
		;
		invoke	GetModuleHandle, 0
		test	eax, eax
		jz	error
		mov	[hInstance], eax

		invoke	LoadIcon, eax, ID_MAINICON
		test	eax, eax
		jz	error
		mov	[MainClass.hIcon], eax

		invoke	LoadCursor, 0, IDC_ARROW
		test	eax, eax
		jz	error
		mov	[MainClass.hCursor], eax

		; Zarejestrowanie używanych w programie klas okien.
		;
		invoke	RegisterClass, MainClass
		test	ax, ax
		jz	error

		invoke	RegisterClass, CharPanelClass
		test	ax, ax
		jz	error

		invoke	RegisterClass, PassPanelClass
		test	ax, ax
		jz	error

		invoke	CreateWindowEx, 0, _MainClass, <"SimPaGen v.", PROG_VERSION>, WS_VISIBLE + WS_SYSMENU + WS_CAPTION + WS_MINIMIZEBOX,\
				144, 128, 300, 332, NULL, 0, [hInstance], NULL
		test	eax, eax
		jz	error

	; Pętla, w której dokonujemy przetworzenia komunikatów dotyczących naszego
	; okna aplikacji.
	;
	msg_loop:
		invoke	GetMessage, msg, NULL, 0, 0
		cmp	eax, -1
		je	error

		cmp	eax, 1
		jb	end_loop
		jne	msg_loop

		; Sprawdzamy, czy dany komunikat dotyczy któregoś z paneli. Jeśli tak,
		; wówczas przetwarzamy ten komunikat w celu odpowiedniej interpretacji
		; naciśnięcia takich klawiszy, jak TAB i klawisze sterujące kursorem
		; (wybór określonych kontrolek panelu).
 		;
		invoke	IsDialogMessage, [PassPanel], msg
		test	eax, eax
		jnz	msg_loop

		invoke	IsDialogMessage, [CharPanel], msg
		test	eax, eax
		jnz	msg_loop

		invoke	TranslateMessage, msg
		invoke	DispatchMessage, msg
		jmp	msg_loop

	error:
		stdcall	ShowLastError, NULL

	end_loop:
		invoke	ExitProcess, [msg.wParam]


; Procedura obsługi okna aplikacji.
;
proc	WindowProc, hwnd, wmsg, wparam, lparam

	locals
		Disposition	dd ?
	endl

	push	ebx esi edi

	cmp	[wmsg], WM_CREATE
	je	.wmcreate
	cmp	[wmsg], WM_DESTROY
	je	.wmdestroy

	.defwndproc:
		invoke	DefWindowProc, [hwnd], [wmsg], [wparam], [lparam]
		jmp	.finish

	.wmcreate:
		; Utworzenie czcionki używanej do wyświetlania napisów etykiet, na przyciskach
		; oraz w oknach tekstowych.
		;
		invoke	CreateFont, 16, 0, 0, 0, 0, FALSE, FALSE, FALSE,\
				DEFAULT_CHARSET, OUT_RASTER_PRECIS, CLIP_DEFAULT_PRECIS,\
				DEFAULT_QUALITY, FIXED_PITCH + FF_DONTCARE, "Tahoma"

		test	eax, eax
		jz	.failed
		mov	[Font], eax

		; Utworzenie klucza rejestru (lub otwarcie go, jeśli wcześniej istniał)
		; przypisanego do bieżącej aplikacji.
		;
		lea	ebx, [Disposition]
		invoke	RegCreateKeyEx, HKEY_CURRENT_USER, .KeyName, 0, 0, REG_OPTION_NON_VOLATILE,\
					KEY_ALL_ACCESS, 0, .hKey, ebx

		test	eax, eax
		jnz	.failed

		; Sprawdzenie, czy wartość wpisanej przez funkcję 'RegCreateKeyEx' do zmiennej
		; lokalnej 'Disposition' informuje o fakcie utworzenia klucza rejestru.
		;
		cmp	dword [ebx], REG_CREATED_NEW_KEY
		jne	.CreatePanels

		; Jeśli tak, to do klucza rejestru wpisywane są domyślne, startowe wartości
		; określające długość hasła oraz funkcję charakterystyczną zbioru znaków
		; składowych tworzonych haseł.
		;
		.SaveStartRegValues:
			; Zarezerwowanie bloku pamięci używanego podczas wpisywania wartości
			; do klucza rejestru skojarzonego z programem.
			;
			invoke	LocalAlloc, LMEM_ZEROINIT, 29
			test	eax, eax
			jz	.failed
			xchg	ebx, eax

			; Zapisanie stanu pól wyboru określających użycie predefiniowanych kategorii
			; znaków (domyślnie użyte są litery A-Z oraz cyfry 0-9).
			;
			mov	byte [ebx], 5			; [A-Z] + [0-9]

			invoke	RegSetValueEx, [.hKey], .FlagsRegVal, 0, REG_BINARY, ebx, 2
			test	eax, eax
			jnz	.failed

			; Zapis funkcji charakterystycznej zbioru składowych (bez uwzględnienia
			; predefiniowanych kategorii).
			;
			lea	eax, [ebx + 1]			; eax := ebx + 1

			invoke	RegSetValueEx, [.hKey], .CharFunRegVal, 0, REG_BINARY, eax, 28
			test	eax, eax
			jnz	.failed

			; Zwolnienie bloku pamięci używanego do operacji na rejestrze Windows.
			;
			invoke	LocalFree, ebx
			test	eax, eax
			jnz	.failed

			; Zapis w kluczu rejestru skojarzonym z programem łańcucha znaków
			; określającego standardową długość hasła.
			;
			invoke	RegSetValueEx, [.hKey], .PassLenRegVal, 0, REG_SZ, PassLen, 10
			test	eax, eax
			jnz	.failed

		.CreatePanels:

			; Utworzenie panelu, w którym generowane są hasła.
			;
			invoke	CreateWindowEx, NULL,\
					_PassPanelClass, 0,\
					WS_VISIBLE + WS_CHILD,\
					15, 10, 265, 172, [hwnd], 0, [hInstance], NULL

			test	eax, eax
			jz	.failed
			mov	[PassPanel], eax

			; Utworzenie panelu, w którym definiujemy zbiór znaków składowych tworzonych
			; haseł.
			;
			invoke	CreateWindowEx, NULL,\
					_CharPanelClass, 0,\
					WS_VISIBLE + WS_CHILD,\
					15, 192, 265, 95, [hwnd], 0, [hInstance], NULL

			test	eax, eax
			jz	.failed
			mov	[CharPanel], eax

			; Pobranie zapisanej w skojarzonym z programem kluczu rejestru funkcji
			; charakterystycznej zbioru znaków składowych.
			;
			invoke	RegQueryValueEx, [.hKey], .CharFunRegVal, 0, 0, CharFun, .CharFunBufSize
			test	eax, eax
			jnz	.failed

			; Pobranie reprezentacji łańcuchowej długości tworzonych haseł.
			;
			invoke	RegQueryValueEx, [.hKey], .PassLenRegVal, 0, 0, PassLen, .PassLenBufSize
			test	eax, eax
			jnz	.failed

			; Umieszczenie tegoż łańcucha znaków w polu tekstowym 'ID_PASSLEN'.
			;
			invoke	SendDlgItemMessage, [PassPanel], ID_PASSLEN, WM_SETTEXT, 0, PassLen

			; Rezerwacja bloku pamięci używanego do przechowania zbioru znaków zdefiniowanych
			; przez użytkownika.
			;
			invoke	LocalAlloc, LMEM_ZEROINIT, 450
			test	eax, eax
			jz	.failed
			xchg	edi, eax
			mov	esi, edi

			; Pętla, w której przetwarzamy funkcję charakterystyczną zbioru znaków w łańcuch
			; znaków Unikodu zawierający znaki składowe zdefiniowane przez użytkownika.
			;
			mov	eax, 31
			xor	ebx, ebx

			.CreateOtherLoop:
				inc	al

				bt	[CharFun - 4], eax
				setc	bl			; CharTab[x] := al
				mov	byte [edi], al		; x := x + 2*CharFun[eax - 32]
				adc	edi, ebx

				test	al, al
				jnz	.CreateOtherLoop

			; Umieszczenie zbioru znaków składowych w polu tekstowym 'ID_PASSCHARS'.
			;
			invoke	SendDlgItemMessage, [CharPanel], ID_PASSCHARS, WM_SETTEXT, 0, esi

			; Pobranie zapisanego w rejestrze systemowym zestawu flag określających
			; stan pól wyboru odpowiadających predefiniowanym kategoriom znaków.
			;
			invoke	RegQueryValueEx, [.hKey], .FlagsRegVal, 0, 0, esi, .FlagsBufSize
			test	eax, eax
			jnz	.failed

			movzx	ebx, word [esi]

			; W zależności od wartości danych flag określamy stan pól wyboru.
			;
			.CheckBox_AZ:
				bt	ebx, 0
				jnc	.CheckBox_az

				invoke	SendDlgItemMessage, [CharPanel], ID_CHKBOX1, BM_CLICK, 0, 0

			.CheckBox_az:
				bt	ebx, 1
				jnc	.CheckBox_09

				invoke	SendDlgItemMessage, [CharPanel], ID_CHKBOX2, BM_CLICK, 0, 0

			.CheckBox_09:
				bt	ebx, 2
				jnc	.CheckBox__

				invoke	SendDlgItemMessage, [CharPanel], ID_CHKBOX3, BM_CLICK, 0, 0

			.CheckBox__:
				bt	ebx, 3
				jnc	.FreeMem

				invoke	SendDlgItemMessage, [CharPanel], ID_CHKBOX4, BM_CLICK, 0, 0

			.FreeMem:
				; Zwolnienie bloku pamięci wykorzystywanego do przechowywania
				; zbioru znaków zdefiniowanych przez użytkownika.
				;
				invoke	LocalFree, esi
				test	eax, eax
				jnz	.failed

		; Symulacja naciśnięcia klawisza 'Utwórz' w celu wygenerowania przykładowego
		; hasła.
		;
		invoke	SendDlgItemMessage, [PassPanel], ID_GENBTN, BM_CLICK, 0, 0

		xor	eax, eax
		jmp	.finish

	.failed:
		stdcall	ShowLastError, [hwnd]
		or	eax, -1
		jmp	.finish

	.wmdestroy:
		;
		; Zapisanie ustawień programu w kluczu rejestru skojarzonym z aplikacją.
		;

		; Pobranie do tablicy 'CharFun' funkcji charakterystycznej zbioru znaków
		; składowych.
		;
		invoke	SendMessage, [CharPanel], WM_GETCHARSET, 0, 0

		; W zależności od wartości flag wykluczamy z funkcji charakterystycznej
		; predefiniowane kategorie znaków.
		;
		movzx	ebx, [Flags]

		.Modify_AZ:
			bt	ebx, 0
			jnc	.Modify_az

			xor	[CharFun + 4], 07FFFFFEh
		.Modify_az:
			bt	ebx, 1
			jnc	.Modify_09

			xor	[CharFun + 8], 07FFFFFEh
		.Modify_09:
			bt	ebx, 2
			jnc	.Modify__

			xor	[CharFun], 03FF0000h
		.Modify__:
			bt	ebx, 3
			jnc	.SaveRegKeyVals

			btr	dword [CharFun + 4], 31

		; Zapisanie łańcuchowej reprezentacji długości tworzonych haseł, zmodyfikowanej
		; funkcji charakterystycznej zbioru znaków oraz zestawu flag w kluczu rejestru.
		;
		.SaveRegKeyVals:

			invoke	RegSetValueEx, [.hKey], .CharFunRegVal, 0, REG_BINARY, CharFun, 28
			test	eax, eax
			jnz	.failed

			invoke	SendDlgItemMessage, [PassPanel], ID_PASSLEN, WM_GETTEXT, 5, PassLen

			invoke	RegSetValueEx, [.hKey], .PassLenRegVal, 0, REG_SZ, PassLen, 10
			test	eax, eax
			jnz	.failed

			invoke	RegSetValueEx, [.hKey], .FlagsRegVal, 0, REG_BINARY, Flags, 2
			test	eax, eax
			jnz	.failed

		; Zamknięcie klucza rejestru skojarzonego z aplikacją.
		;
		invoke	RegCloseKey, [.hKey]
		test	eax, eax
		jnz	.failed

		; Usunięcie utworzonej czcionki.
		;
		invoke	DeleteObject, [Font]
		test	eax, eax
		jz	.failed

		invoke	PostQuitMessage, 0
		xor	eax, eax

	.finish:
		pop	edi esi ebx

		ret

	align 4

	; Zmienne wykorzystywane podczas operacji na kluczu rejestru.
	;
	.CharFunBufSize	dd 28
	.PassLenBufSize	dd 10
	.FlagsBufSize	dd 2

	.hKey		dd ?

	.KeyName	du 'Software\SimPaGen\', PROG_VERSION, 0
	.CharFunRegVal	du 'CharFun', 0
	.PassLenRegVal	du 'PassLen', 0
	.FlagsRegVal	du 'Flags', 0

endp


; Procedura obsługi panelu, w którym dochodzi do generowania haseł.
;
proc	PassPanelProc, hwnd, wmsg, wparam, lparam

	locals	
		Password	dd ?
		PassLen		dd ?
		CharTabLen	dd ?
	endl

	; Typ dostarczyciela usług kryptograficznych (CSP) wykorzystywanego
	; do generowania losowego ciągu znaków hasła.
	;
	PROV_RSA_FULL	= 1

	; Stałe przechowujące identyfikatory kontrolek panelu.
	;
	ID_GENBTN	= 101
	ID_CLIPBTN	= 102

	ID_PASSEDIT	= 201
	ID_PASSLEN	= 202

	; Identyfikator skrótu klawiszowego WIN + F12.
	;
	ID_HOTKEY	= 1

	; Zdefiniowanie stałych przechowujących kody komunikatów użytkownika
	; wykorzystywanych do komunikacji z polami tekstowymi programu.
	;
	; Stałym nadajemy wartość równą WM_USER + 2 w celu uniknięcia możliwych
	; konfliktów z komunikatami DM_GETDEFID i DM_SETDEFID, równymi
	; odpowiednio WM_USER i WM_USER + 1, które może wygenerować funkcja
	; 'IsDialogMessage'.
	;
	WM_GETPASSLEN	= WM_USER + 2
	WM_GETCHARSET	= WM_USER + 2

	push	ebx ecx edx esi edi

	cmp	[wmsg], WM_CREATE
	je	.wmcreate
	cmp	[wmsg], WM_COMMAND
	je	.wmcommand
	cmp	[wmsg], WM_HOTKEY
	je	.wmhotkey
	cmp	[wmsg], WM_DESTROY
	je	.wmdestroy

	.defwndproc:
		invoke	DefWindowProc, [hwnd], [wmsg], [wparam], [lparam]
		jmp	.finish

	.wmcreate:
		; Określenie dostarczyciela usług kryptograficznych i umieszczenie
		; uchwytu tegoż w zmiennej '.hProv'.
		;
		invoke	CryptAcquireContext, .hProv, NULL, NULL, PROV_RSA_FULL, 0
		test	eax, eax
		jz	.failed

		invoke	CreateWindowEx, NULL,\
				_button, 0,\
				WS_VISIBLE + WS_CHILD + BS_GROUPBOX,\
				0, 0, 265, 172, [hwnd], 0, [hInstance], NULL

		test	eax, eax
		jz	.failed
		xchg	ebx, eax

		invoke	SendMessage, ebx, WM_SETFONT, [Font], FALSE

		invoke	SetWindowText, ebx, "Hasło"
		test	eax, eax
		jz	.failed

		invoke	CreateWindowEx, WS_EX_CLIENTEDGE,\
				_edit, 0,\
				WS_VISIBLE + WS_CHILD + WS_VSCROLL + ES_READONLY + ES_AUTOVSCROLL + ES_MULTILINE,\
				15, 25, 235, 80, [hwnd], ID_PASSEDIT, [hInstance], NULL

		test	eax, eax
		jz	.failed

		invoke	SendMessage, eax, WM_SETFONT, [Font], FALSE

		invoke	CreateWindowEx, NULL,\
				_static, 0,\
				WS_VISIBLE + WS_CHILD + SS_RIGHT,\
				15, 128, 50, 20, [hwnd], 0, [hInstance], NULL

		test	eax, eax
		jz	.failed
		xchg	ebx, eax

		invoke	SendMessage, ebx, WM_SETFONT, [Font], FALSE

		invoke	SetWindowText, ebx, "Długość:"
		test	eax, eax
		jz	.failed

		invoke	CreateWindowEx, WS_EX_CLIENTEDGE,\
				_edit, 0,\
				WS_VISIBLE + WS_CHILD + ES_RIGHT + WS_TABSTOP,\
				70, 128, 50, 20, [hwnd], ID_PASSLEN, [hInstance], NULL

		test	eax, eax
		jz	.failed
		xchg	ebx, eax

		; Zastąpienie domyślnej procedury obsługi pola tekstowego 'ID_PASSLEN' procedurą
		; zdefiniowaną w programie.
		;
		invoke	SetWindowLong, ebx, GWL_WNDPROC, PassLenEditProc
		test	eax, eax
		jz	.failed
		mov	[PassLenEditProc.OldWndProc], eax

		; Ograniczenie do 4 ilości znaków możliwych do wprowadzenia do pola tekstowego
		; 'ID_PASSLEN'.
		;
		invoke	SendMessage, ebx, EM_SETLIMITTEXT, 4, 0

		invoke	SendMessage, ebx, WM_SETFONT, [Font], FALSE

		invoke	CreateWindowEx, NULL,\
				_button, 0,\
				WS_VISIBLE + WS_CHILD + WS_TABSTOP + BS_ICON,\
				133, 120, 36, 36, [hwnd], ID_CLIPBTN, [hInstance], NULL

		test	eax, eax
		jz	.failed

		; Załadowanie ikony i umieszczenie jej na przycisku służącym do kopiowania
		; wygenerowanego hasła do schowka.
		;
		invoke	LoadIcon, [hInstance], ID_COPYICON
		test	eax, eax
		jz	.failed

		invoke	SendDlgItemMessage, [hwnd], ID_CLIPBTN, BM_SETIMAGE, IMAGE_ICON, eax

		invoke	CreateWindowEx, NULL,\
				_button, 0,\
				WS_VISIBLE + WS_CHILD + WS_TABSTOP + BS_DEFPUSHBUTTON,\
				180, 119, 70, 38, [hwnd], ID_GENBTN, [hInstance], NULL

		test	eax, eax
		jz	.failed
		xchg	ebx, eax

		invoke	SendMessage, ebx, WM_SETFONT, [Font], FALSE

		invoke	SetWindowText, ebx, "Utwórz"
		test	eax, eax
		jz	.failed

		; Zarezerwowanie bloku pamięci niezbędnego do przechowania zbioru znaków
		; składowych hasła.
		;
		invoke	LocalAlloc, LMEM_ZEROINIT, 224
		test	eax, eax
		jz	.failed
		mov	[.CharTab], eax

		; Rejestracja skrótu klawiszowego WIN + F12 i skojarzenie go z oknem aplikacji.
		;
		invoke	RegisterHotKey, [hwnd], ID_HOTKEY, MOD_WIN, VK_F12
		test	eax, eax
		jz	.failed

		xor	eax, eax
		jmp	.finish

	.failed:
		stdcall	ShowLastError, [hwnd]
		or	eax, -1
		jmp	.finish

	.wmcommand:
		mov	eax, [wparam]
		and	eax, 0FFFFh
		cmp	eax, ID_CLIPBTN
		je	.copy
		cmp	eax, ID_GENBTN
		jne	.defwndproc

	; Operacje wykonywane w przypadku naciśnięcia przycisku 'Utwórz'.
	;
	.GenBtn:

		; Wysłanie do pola tekstowego 'ID_PASSLEN' komunikatu użytkownika w celu określenia
		; ilości znaków generowanego hasła.
		;
		invoke	SendDlgItemMessage, [hwnd], ID_PASSLEN, WM_GETPASSLEN, 0, 0
		test	eax, eax
		jz	.clear
		mov	[PassLen], eax

		; Wysłanie do panelu, w którym definiowany jest zbiór znaków używanych do generowania
		; haseł, komunikatu użytkownika w celu określenia zdefiniowanego przez użytkownika
		; zbioru znaków dodatkowych. 
		;
		invoke	SendMessage, [CharPanel], WM_GETCHARSET, 0, 0

		; Pętla, w której przetwarzamy funkcję charakterystyczną zbioru znaków w tablicę
		; zawierającą znaki tworzonych haseł.
		;
		mov	edi, [.CharTab]
		mov	eax, 31

		.FillCharTabLoop:
			inc	al

			bt	[CharFun - 4], eax
			mov	byte [edi], al		; CharTab[x] := al
			adc	edi, 0			; x := x + CharFun[eax - 32]

			test	al, al
			jnz	.FillCharTabLoop

		; Określenie długości tablicy znaków.
		;
		sub	edi, [.CharTab]

		test	edi, edi
		jz	.clear

		mov	[CharTabLen], edi

		; Przetworzenie długości hasła w znakach w ilość bajtów niezbędnych
		; do przechowania wygenerowanego hasła.
		;
		mov	ebx, [PassLen]
		shl	ebx, 1
		mov	eax, ebx
		add	eax, 2

		; Rezerwacja bloku pamięci przeznaczonego dla tworzonego hasła.
		;
		invoke	LocalAlloc, LMEM_ZEROINIT, eax
		test	eax, eax
		jz	.failed

		mov	[Password], eax

		; Wypełnienie przygotowanego bufora losową zawartością.
		;
		invoke	CryptGenRandom, [.hProv], ebx, eax
		test	eax, eax
		jz	.failed

		; Pętla, w której bajty wygenerowanego hasła są przetwarzane w znaki
		; należące do dozwolonego zbioru symboli.
		;
		mov	ecx, [PassLen]
		mov	esi, [Password]
		mov	edi, esi
		mov	ebx, [.CharTab]

		cld

		.GenPasswordLoop:
			xor	edx, edx
			lodsw				;
			div	[CharTabLen]		;
			movzx	ax, byte [ebx + edx]	; Password[x] := CharTab[Password[x] mod CharTabLen]
			stosw				;
			loop	.GenPasswordLoop

		; Wyświetlenie wygenerowanego hasła w polu tekstowym 'ID_PASSEDIT'.
		;
		invoke	SendDlgItemMessage, [hwnd], ID_PASSEDIT, WM_SETTEXT, 0, [Password]

		; Zwolnienie pamięci przeznaczonej dla hasła.
		;
		invoke	LocalFree, [Password]
		test	eax, eax
		jnz	.failed

		jmp	.finish

	; Operacje wykonywane w przypadku naciśnięcia skrótu klawiszowego WIN + F12.
	;
	.wmhotkey:
		cmp	[wparam], ID_HOTKEY
		jne	.finish

		; Wygenerowanie nowego hasła.
		;
		invoke	SendDlgItemMessage, [hwnd], ID_GENBTN, BM_CLICK, 0, 0

	; Skopiowanie hasła do schowka w przypadku naciśnięcia przycisku z ikoną lub
	; użycia skrótu klawiszowego WIN + F12.
	;
	.copy:
		; Określenie długości hasła (w znakach) i przeliczenie jej na ilość
		; bajtów bufora przeznaczonego do przechowywania tekstu pobranego 
		; z pola hasłowego.
		;
		invoke	SendDlgItemMessage, [hwnd], ID_PASSEDIT, WM_GETTEXTLENGTH, 0, 0
		inc	eax
		mov	ebx, eax
		shl	eax, 1

		; Alokacja bloku pamięci dla pobieranego hasła.
		;
		invoke	GlobalAlloc, GHND + GMEM_DDESHARE, eax		; GHND = GMEM_MOVEABLE + GMEM_ZEROINIT
		test	eax, eax
		jz	.failed

		; Zablokowanie bloku pamięci i pobranie wskaźnika na jego pierwszy bajt.
		;
		invoke	GlobalLock, eax
		test	eax, eax
		jz	.failed
		xchg	esi, eax

		; Otwarcie schowka i zablokowanie możliwości modyfikacji jego zawartości
		; przez inne aplikacje.
		;
		invoke	OpenClipboard, [hwnd]
		test	eax, eax
		jz	.failed

		; Opróżnienie schowka, zwolnienie uchwytów bloków danych znajdujących się
		; w nim oraz skojarzenie schowka z oknem bieżącej aplikacji.
		;
		invoke	EmptyClipboard
		test	eax, eax
		jz	.failed

		; Pobranie hasła i umieszczenie go w wydzielonym buforze.
		;
		invoke	SendDlgItemMessage, [hwnd], ID_PASSEDIT, WM_GETTEXT, ebx, esi

		; Umieszczenie treści hasła w schowku w formacie Unicode.
		;
		invoke	SetClipboardData, CF_UNICODETEXT, esi
		test	eax, eax
		jz	.failed

		; Odblokowanie obszaru pamięci używanego jako bufor dla pobieranego hasła.
		;
		invoke	GlobalUnlock, esi
		test	eax, eax
		jz	.failed

		; Zamknięcie schowka i umożliwienie dostępu do niego pozostałym aplikacjom.
		;
		invoke	CloseClipboard
		test	eax, eax
		jz	.failed

		jmp	.finish

	; Wyczyszczenie pola tekstowego 'ID_PASSEDIT' w przypadku, gdy zbiór znaków składowych
	; jest pusty lub długość hasła jest równa 0.
	;
	.clear:
		invoke	SendDlgItemMessage, [hwnd], ID_PASSEDIT, WM_SETTEXT, 0, 0
		jmp	.finish

	.wmdestroy:
		; Wyrejestrowanie skrótu klawiszowego WIN + F12 skojarzonego z bieżącą aplikacją.
		;
		invoke	UnregisterHotKey, [hwnd], ID_HOTKEY
		test	eax, eax
		jz	.failed

		; Zwolnienie bloku pamięci używanego do przechowywania tablicy
		; znaków składowych tworzonych haseł.
		;
		invoke	LocalFree, [.CharTab]
		test	eax, eax
		jnz	.failed

		; Zwolnienie uchwytu dostarczyciela usług kryptograficznych.
		;
		invoke	CryptReleaseContext, [.hProv], 0
		test	eax, eax
		jz	.failed

		xor	eax, eax

	.finish:
		pop	edi esi edx ecx ebx
		ret

	align 4

	; Uchwyt tablicy znaków składowych haseł.
	;
	.CharTab	dd ?

	; Uchwyt dostarczyciela usług kryptograficznych.
	;
	.hProv		dd ?
endp


; Nowa procedura obsługi pola tekstowego służącego do określania długości generowanego
; hasła. 
;
proc	PassLenEditProc, hwnd, wmsg, wparam, lparam

	cmp	[wmsg], WM_CHAR
	je	.wmchar
	cmp	[wmsg], WM_GETPASSLEN
	je	.wmuser
	cmp	[wmsg], WM_PASTE	; Blokada możliwości wklejania tekstu
	je	.finish			; w pole tekstowe.

	.defwndproc:
		invoke	CallWindowProc, [.OldWndProc], [hwnd], [wmsg], [wparam], [lparam]
		jmp	.finish

	; Pole tekstowe akceptuje tylko znaki '0', ..., '9' oraz 'backspace'.
	;
	.wmchar:
		mov	eax, [wparam]

		cmp	eax, VK_BACK
		je	.defwndproc

		cmp	eax, '0'
		jb	.finish
		cmp	eax, '9'
		ja	.finish

		jmp	.defwndproc

	; Po otrzymaniu komunikatu WM_GETPASSLEN pole tekstowe oblicza wartość
	; liczbową odpowiadającą przechowywanemu ciągowi cyfr dziesiętnych i umieszcza
	; ją w rejestrze eax, dzięki czemu będzie ona dostępna w procedurze, która
	; wysłała tenże komunikat.
	;
	.wmuser:
		push	ebx esi

		; Pobranie zawartości pola tekstowego.
		;
		lea	esi, [PassLen]
		invoke	SendMessage, [hwnd], WM_GETTEXT, 5, esi

		; Pętla, w której obliczamy wartość liczbową odpowiadającą ciągowi
		; cyfr dziesiątkowych.
		;
		xor	eax, eax
		xor	ebx, ebx

		cld

		.Loop:
			lodsw

			test	eax, eax
			jz	.LoopEnd

			; ebx := 10*ebx + (eax - '0')
			;
			lea	ebx, [ebx + 4*ebx]	; ebx := ebx + 4*ebx = 5*ebx
			shl	ebx, 1			; ebx := 2*ebx
			sub	al, '0'			;
			add	ebx, eax		; ebx := ebx + (eax - '0')

			jmp	.Loop

		.LoopEnd:
			xchg	eax, ebx

		pop	esi ebx

	.finish:
		ret

	align 4

	; Uchwyt starej procedury obsługi okna tekstowego.
	;
	.OldWndProc	dd ?
endp


; Procedura obsługi panelu, w którym definiujemy zbiór znaków składowych
; dla generowanych haseł.
;
proc	CharPanelProc, hwnd, wmsg, wparam, lparam

	; Definicje stałych przechowujących identyfikatory kontrolek panelu.
	;
	ID_CHKBOX1	= 1
	ID_CHKBOX2	= 2
	ID_CHKBOX3	= 3
	ID_CHKBOX4	= 4

	ID_PASSCHARS	= 101

	push	ebx

	cmp	[wmsg], WM_CREATE
	je	.wmcreate
	cmp	[wmsg], WM_COMMAND
	je	.wmcommand
	cmp	[wmsg], WM_GETCHARSET
	je	.wmuser
	cmp	[wmsg], WM_DESTROY
	je	.wmdestroy

	.defwndproc:
		invoke	DefWindowProc, [hwnd], [wmsg], [wparam], [lparam]
		jmp	.finish

	.wmcreate:
		invoke	CreateWindowEx, NULL,\
				_button, 0,\
				WS_VISIBLE + WS_CHILD + BS_GROUPBOX,\
				0, 0, 265, 95, [hwnd], 0, [hInstance], NULL

		test	eax, eax
		jz	.failed
		xchg	ebx, eax

		invoke	SendMessage, ebx, WM_SETFONT, [Font], FALSE

		invoke	SetWindowText, ebx, "Symbole składowe"
		test	eax, eax
		jz	.failed

		invoke	CreateWindowEx, NULL,\
				_button, 0,\
				WS_VISIBLE + WS_CHILD + BS_AUTOCHECKBOX + WS_TABSTOP,\
				27, 25, 40, 17, [hwnd], ID_CHKBOX1, [hInstance], NULL

		test	eax, eax
		jz	.failed
		xchg	ebx, eax

		invoke	SendMessage, ebx, WM_SETFONT, [Font], FALSE

		invoke	SetWindowText, ebx, "A-Z"
		test	eax, eax
		jz	.failed

		invoke	CreateWindowEx, NULL,\
				_button, 0,\
				WS_VISIBLE + WS_CHILD + BS_AUTOCHECKBOX + WS_TABSTOP,\
				87, 25, 40, 17, [hwnd], ID_CHKBOX2, [hInstance], NULL

		test	eax, eax
		jz	.failed
		xchg	ebx, eax

		invoke	SendMessage, ebx, WM_SETFONT, [Font], FALSE

		invoke	SetWindowText, ebx, "a-z"
		test	eax, eax
		jz	.failed

		invoke	CreateWindowEx, NULL,\
				_button, 0,\
				WS_VISIBLE + WS_CHILD + BS_AUTOCHECKBOX + WS_TABSTOP,\
				147, 25, 40, 17, [hwnd], ID_CHKBOX3, [hInstance], NULL

		test	eax, eax
		jz	.failed
		xchg	ebx, eax

		invoke	SendMessage, ebx, WM_SETFONT, [Font], FALSE

		invoke	SetWindowText, ebx, "0-9"
		test	eax, eax
		jz	.failed

		invoke	CreateWindowEx, NULL,\
				_button, 0,\
				WS_VISIBLE + WS_CHILD + BS_AUTOCHECKBOX + WS_TABSTOP,\
				207, 25, 40, 17, [hwnd], ID_CHKBOX4, [hInstance], NULL

		test	eax, eax
		jz	.failed
		xchg	ebx, eax

		invoke	SendMessage, ebx, WM_SETFONT, [Font], FALSE

		invoke	SetWindowText, ebx, "_"
		test	eax, eax
		jz	.failed

		invoke	CreateWindowEx, NULL,\
				_static, 0,\
				WS_VISIBLE + WS_CHILD + SS_RIGHT,\
				27, 60, 50, 20, [hwnd], 0, [hInstance], NULL

		test	eax, eax
		jz	.failed
		xchg	ebx, eax

		invoke	SendMessage, ebx, WM_SETFONT, [Font], FALSE

		invoke	SetWindowText, ebx, "Inne:"
		test	eax, eax
		jz	.failed

		invoke	CreateWindowEx, WS_EX_CLIENTEDGE,\
				_edit, 0,\
				WS_VISIBLE + WS_CHILD + ES_AUTOHSCROLL + WS_TABSTOP,\
				82, 60, 155, 20, [hwnd], ID_PASSCHARS, [hInstance], NULL

		test	eax, eax
		jz	.failed
		xchg	ebx, eax

		invoke	SendMessage, ebx, WM_SETFONT, [Font], FALSE

		; Zastąpienie standardowej procedury obsługi pola tekstowego 'ID_PASSCHARS' procedurą
		; zdefiniowaną w programie.
		;
		invoke	SetWindowLong, ebx, GWL_WNDPROC, PassCharsEditProc
		test	eax, eax
		jz	.failed
		mov	[PassCharsEditProc.OldWndProc], eax

		xor	eax, eax
		jmp	.finish

	.failed:
		stdcall	ShowLastError, [hwnd]
		or	eax, -1
		jmp	.finish

	; Jeśli zdarzenie związane jest ze zmianą stanu któregoś z pól wyboru,
	; wówczas zmieniamy wartość odpowiedniej flagi.
	;
	.wmcommand:
		mov	eax, [wparam]
		and	eax, 0FFFFh
		jz	.defwndproc

		cmp	eax, ID_CHKBOX4
		ja	.defwndproc

		dec	eax
		btc	[Flags], ax

		jmp	.defwndproc

	; W przypadku przechwycenia komunikatu WM_GETCHARSET transmitujemy go do pola
	; tekstowego 'ID_PASSCHARS', które w odpowiedzi dokona modyfikacji funkcji
	; charakterystycznej zbioru znaków uwzględniając znaki dodane przez użytkownika.
	;
	.wmuser:
		invoke	SendDlgItemMessage, [hwnd], ID_PASSCHARS, WM_GETCHARSET, 0, 0
		jmp	.finish

	.wmdestroy:
		xor	eax, eax

	.finish:
		pop	ebx
		ret

endp


; Nowa procedura obsługi pola tekstowego służącego do definiowania dostosowanego
; do potrzeb użytkownika zbioru znaków dla generowanych haseł.
;
proc	PassCharsEditProc, hwnd, wmsg, wparam, lparam

	locals
		Buffer	dd ?
	endl

	cmp	[wmsg], WM_CHAR
	je	.wmchar
	cmp	[wmsg], WM_GETCHARSET
	je	.wmuser
	cmp	[wmsg], WM_PASTE	; Blokujemy możliwość wklejania
	je	.finish			; tekstu do pola tekstowego.

	.defwndproc:
		invoke	CallWindowProc, [.OldWndProc], [hwnd], [wmsg], [wparam], [lparam]
		jmp	.finish

	; Ograniczenie zbioru znaków możliwych do wpisania z klawiatury do symboli o kodach
	; od 20h do FFh oraz znaku 'backspace'.
	;
	.wmchar:
		mov	eax, [wparam]

		cmp	eax, VK_BACK
		je	.defwndproc

		cmp	eax, 20h
		jb	.finish
		cmp	ax, 0FFh
		ja	.finish

		jmp	.defwndproc

	.failed:
		stdcall	ShowLastError, [hwnd]
		or	eax, -1
		jmp	.finish

	; W przypadku przechwycenia komunikatu użytkownika zawartość pola tekstowego jest
	; przetwarzania w celu uzupełnienia funkcji charakterystycznej zestawu znaków
	; o symbole dodatkowe podane przez użytkownika.
	;
	.wmuser:
		push	ebx ecx esi edi

		; Wyczyszczenie zawartości tablicy definiującej funkcję charakterystyczną
		; zbioru znaków składowych.
		;
		xor	eax, eax
		mov	ecx, 7
		mov	edi, CharFun
		cld
		rep	stosd

		; Informacja o stanie pól wyboru kopiowana jest do rejestru ebx.
		;
		movzx	ebx, [Flags]

		; Jeśli flaga odpowiadająca któremukolwiek z pól wyboru jest ustawiona,
		; wówczas funkcja charakterystyczna jest uzupełniana odpowiednią bazową
		; kategorią znaków.
		;
		.Check_AZ:
			bt	ebx, 0
			jnc	.Check_az

			or	[CharFun + 4], 07FFFFFEh
		.Check_az:
			bt	ebx, 1
			jnc	.Check_09

			or	[CharFun + 8], 07FFFFFEh
		.Check_09:
			bt	ebx, 2
			jnc	.Check__

			or	[CharFun], 03FF0000h
		.Check__:
			bt	ebx, 3
			jnc	.OtherChars

			bts	dword [CharFun + 4], 31

		; Uzupełnienie funkcji charakterystycznej zestawu znaków o symbole podane
		; przez użytkownika.
		;
		.OtherChars:
			; Określenie długości tekstu przechowywanego w polu tekstowym.
			;
			invoke	SendMessage, [hwnd], WM_GETTEXTLENGTH, 0, 0
			inc	eax
			mov	ebx, eax
			shl	eax, 1

			; Zarezerwowanie bloku pamięci przeznaczonego na tekst pobrany
			; z pola tekstowego.
			;
			invoke	LocalAlloc, LMEM_ZEROINIT, eax
			test	eax, eax
			jz	.failed

			mov	[Buffer], eax

			; Umieszczenie zawartości pola tekstowego w zarezerwowanym buforze.
			;
			invoke	SendMessage, [hwnd], WM_GETTEXT, ebx, eax

			; Pętla, w której ustawiamy bity tablicy przechowującej funkcję
			; charakterystyczną zbioru znaków odpowiadające kodom znaków
			; zawartych w polu tekstowym.
			;
			xor	eax, eax
			mov	esi, [Buffer]

			cld

			.Loop:
				lodsw

				test	eax, eax
				jz	.LoopEnd

				bts	[CharFun - 4], eax	; CharFun[eax - 32] := 1

				jmp	.Loop

			.LoopEnd:
				; Zwolnienie bloku pamięci przeznaczonego na tekst pobrany
				; z pola tekstowego.
				;
				invoke	LocalFree, [Buffer]
				test	eax, eax
				jnz	.failed

		pop	edi esi ecx ebx

	.finish:
		ret

	align 4

	; Uchwyt starej procedury obsługi pola tekstowego.
	;
	.OldWndProc	dd ?
endp


; Procedura używana do wyświetlania okienka komunikatu zawierającego informację na temat
; błędu, jaki może wystąpić podczas wykonania programu.
;
proc	ShowLastError, hwnd

	locals
		Buffer dd ?
	endl

	push	ebx

	invoke	GetLastError

	lea	ebx, [Buffer]
	invoke	FormatMessage, FORMAT_MESSAGE_ALLOCATE_BUFFER + FORMAT_MESSAGE_FROM_SYSTEM, 0, eax, LANG_NEUTRAL, ebx, 0, 0
	invoke	MessageBox, [hwnd], [Buffer], NULL, MB_ICONERROR + MB_OK
	invoke	LocalFree, [Buffer]

	pop	ebx

	ret
endp

.end start


; Sekcja, w której definiujemy zasoby programu.
;
section '.rsrc' resource data readable

	RT_MANIFEST	= 24
	ID_MANIFEST	= 1

	ID_MAINICON	= 1
	ID_COPYICON	= 2

	directory	RT_ICON, icons,\
			RT_GROUP_ICON, icon_groups,\
			RT_VERSION, versions,\
			RT_MANIFEST, manifest

	resource	icons,\
			1, LANG_NEUTRAL, main_icon_data,\
			2, LANG_NEUTRAL, copy_icon_data

	resource	icon_groups,\
			ID_MAINICON, LANG_NEUTRAL, main_icon_grp_data,\
			ID_COPYICON, LANG_NEUTRAL, copy_icon_grp_data

	resource	versions,\
			1, LANG_NEUTRAL, version

	resource	manifest,\
			ID_MANIFEST, LANG_NEUTRAL, man

	versioninfo	version, VOS__WINDOWS32, VFT_APP, VFT2_UNKNOWN, LANG_ENGLISH + SUBLANG_DEFAULT, 0,\
			'FileDescription', 'Prosty generator haseł.',\
			'LegalCopyright', '(C) Mikołaj Hajduk, 2008',\
			'FileVersion', PROG_VERSION,\
			'ProductVersion', PROG_VERSION,\
			'OriginalFilename', 'SimPaGen.exe'

	; Dane głównej ikony programu włączonej bezpośrednio w treść pliku źródłowego.
	;
	main_icon_data	dd RVA main_idata, 0x2E8, 0, 0

	main_idata	db	0x28,	0x0,	0x0,	0x0,	0x20,	0x0,	0x0,	0x0
			db	0x40,	0x0,	0x0,	0x0,	0x1,	0x0,	0x4,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0xF9,	0x0,	0xC,	0x0
			db	0xE9,	0x0,	0x2B,	0x0,	0xDC,	0x0,	0x46,	0x0
			db	0xD4,	0x0,	0x56,	0x0,	0xCC,	0x0,	0x67,	0x0
			db	0xC4,	0x0,	0x77,	0x0,	0xBB,	0x0,	0x88,	0x0
			db	0xB3,	0x0,	0x98,	0x0,	0xAB,	0x0,	0xA9,	0x0
			db	0xA3,	0x0,	0xB9,	0x0,	0x9B,	0x0,	0xC9,	0x0
			db	0x92,	0x0,	0xDA,	0x0,	0x8A,	0x0,	0xEA,	0x0
			db	0x82,	0x0,	0xFB,	0x0,	0x0,	0xFF,	0xFF,	0x0
			db	0xFF,	0xFF,	0xFF,	0xFF,	0xFF,	0xFF,	0xFF,	0xFF
			db	0xFF,	0xFF,	0xFF,	0xFF,	0xFF,	0xFF,	0xFF,	0xFF
			db	0xFE,	0xEE,	0xEE,	0xEE,	0xEE,	0xEE,	0xEE,	0xEE
			db	0xEE,	0xEE,	0xEE,	0xEE,	0xEE,	0xEE,	0xEE,	0xEF
			db	0xFD,	0xDD,	0xDD,	0xDD,	0xDD,	0xDD,	0xDD,	0xDD
			db	0xDD,	0xDD,	0xDD,	0xDD,	0xDD,	0xDD,	0xDD,	0xDF
			db	0xFD,	0xDD,	0xDD,	0xDD,	0xDD,	0xDD,	0xDD,	0xDD
			db	0xDD,	0xDD,	0xDD,	0xDD,	0xDD,	0xDD,	0xDD,	0xDF
			db	0xFC,	0xCC,	0xCC,	0xCC,	0xCC,	0xCC,	0xCC,	0xCC
			db	0xCC,	0xCC,	0xCC,	0xCC,	0xCC,	0xCC,	0xCC,	0xCF
			db	0xFC,	0xCC,	0xCC,	0xCC,	0xCC,	0xCC,	0xCC,	0xCC
			db	0xCC,	0xCC,	0xCC,	0xCC,	0xCC,	0xCC,	0xCC,	0xCF
			db	0xFB,	0xBB,	0xBB,	0xBB,	0xBB,	0xBB,	0xBB,	0xBB
			db	0xBB,	0xBB,	0xBB,	0xBB,	0xBF,	0xFB,	0xBB,	0xBF
			db	0xFB,	0xBB,	0xBB,	0xBB,	0xBB,	0xBB,	0xBB,	0xBB
			db	0xBB,	0xBB,	0xBB,	0xBB,	0xBF,	0xFB,	0xBB,	0xBF
			db	0xFA,	0xAA,	0xAA,	0xAA,	0xAA,	0xAA,	0xAA,	0xAA
			db	0xAA,	0xAA,	0xAA,	0xAA,	0xAF,	0xFA,	0xAA,	0xAF
			db	0xFA,	0xAA,	0xAA,	0xAA,	0xAA,	0xAA,	0xAA,	0xAA
			db	0xAA,	0xAA,	0xAA,	0xAA,	0xAF,	0xFA,	0xAA,	0xAF
			db	0xF9,	0x99,	0x99,	0x99,	0x99,	0x99,	0x99,	0x99
			db	0x99,	0x99,	0x99,	0x99,	0x9F,	0xF9,	0x99,	0x9F
			db	0xF9,	0x99,	0x99,	0x99,	0x99,	0x99,	0x99,	0x99
			db	0x99,	0x99,	0x99,	0x99,	0x9F,	0xF9,	0x99,	0x9F
			db	0xF8,	0x88,	0x88,	0x88,	0xFF,	0x88,	0x88,	0x88
			db	0x88,	0xFF,	0x88,	0x88,	0x8F,	0xF8,	0x88,	0x8F
			db	0xF8,	0x88,	0x8F,	0xF8,	0xFF,	0x8F,	0xF8,	0x8F
			db	0xF8,	0xFF,	0x8F,	0xF8,	0x8F,	0xF8,	0x88,	0x8F
			db	0xF7,	0x77,	0x77,	0xFF,	0xFF,	0xFF,	0x77,	0x77
			db	0xFF,	0xFF,	0xFF,	0x77,	0x7F,	0xF7,	0x77,	0x7F
			db	0xF7,	0x77,	0x77,	0x7F,	0xFF,	0xF7,	0x77,	0x77
			db	0x7F,	0xFF,	0xF7,	0x77,	0x7F,	0xF7,	0x77,	0x7F
			db	0xF6,	0x66,	0x66,	0x6F,	0xFF,	0xF6,	0x66,	0x66
			db	0x6F,	0xFF,	0xF6,	0x66,	0x6F,	0xF6,	0x66,	0x6F
			db	0xF6,	0x66,	0x66,	0xFF,	0xFF,	0xFF,	0x66,	0x66
			db	0xFF,	0xFF,	0xFF,	0x66,	0x6F,	0xF6,	0x66,	0x6F
			db	0xF5,	0x55,	0x5F,	0xF5,	0xFF,	0x5F,	0xF5,	0x5F
			db	0xF5,	0xFF,	0x5F,	0xF5,	0x5F,	0xF5,	0x55,	0x5F
			db	0xF5,	0x55,	0x55,	0x55,	0xFF,	0x55,	0x55,	0x55
			db	0x55,	0xFF,	0x55,	0x55,	0x5F,	0xF5,	0x55,	0x5F
			db	0xF4,	0x44,	0x44,	0x44,	0x44,	0x44,	0x44,	0x44
			db	0x44,	0x44,	0x44,	0x44,	0x4F,	0xF4,	0x44,	0x4F
			db	0xF4,	0x44,	0x44,	0x44,	0x44,	0x44,	0x44,	0x44
			db	0x44,	0x44,	0x44,	0x44,	0x4F,	0xF4,	0x44,	0x4F
			db	0xF3,	0x33,	0x33,	0x33,	0x33,	0x33,	0x33,	0x33
			db	0x33,	0x33,	0x33,	0x33,	0x3F,	0xF3,	0x33,	0x3F
			db	0xF3,	0x33,	0x33,	0x33,	0x33,	0x33,	0x33,	0x33
			db	0x33,	0x33,	0x33,	0x33,	0x3F,	0xF3,	0x33,	0x3F
			db	0xF2,	0x22,	0x22,	0x22,	0x22,	0x22,	0x22,	0x22
			db	0x22,	0x22,	0x22,	0x22,	0x2F,	0xF2,	0x22,	0x2F
			db	0xF2,	0x22,	0x22,	0x22,	0x22,	0x22,	0x22,	0x22
			db	0x22,	0x22,	0x22,	0x22,	0x2F,	0xF2,	0x22,	0x2F
			db	0xF2,	0x22,	0x22,	0x22,	0x22,	0x22,	0x22,	0x22
			db	0x22,	0x22,	0x22,	0x22,	0x22,	0x22,	0x22,	0x2F
			db	0xF2,	0x22,	0x22,	0x22,	0x22,	0x22,	0x22,	0x22
			db	0x22,	0x22,	0x22,	0x22,	0x22,	0x22,	0x22,	0x2F
			db	0xF2,	0x22,	0x22,	0x22,	0x22,	0x22,	0x22,	0x22
			db	0x22,	0x22,	0x22,	0x22,	0x22,	0x22,	0x22,	0x2F
			db	0xF1,	0x11,	0x11,	0x11,	0x11,	0x11,	0x11,	0x11
			db	0x11,	0x11,	0x11,	0x11,	0x11,	0x11,	0x11,	0x1F
			db	0xF1,	0x11,	0x11,	0x11,	0x11,	0x11,	0x11,	0x11
			db	0x11,	0x11,	0x11,	0x11,	0x11,	0x11,	0x11,	0x1F
			db	0xFF,	0xFF,	0xFF,	0xFF,	0xFF,	0xFF,	0xFF,	0xFF
			db	0xFF,	0xFF,	0xFF,	0xFF,	0xFF,	0xFF,	0xFF,	0xFF
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
	align 4

	main_icon_grp_data	dd RVA main_icon_grp_header, 20, 0, 0

	main_icon_grp_header	dw 0, 1, 1
				dd 0x102020, 0x40001, 0x2E8
				dw main_icon_data.resid
	align 4

	; Dane ikony wyświetlanej na przycisku służącym do kopiowania wygenerowanego hasła
	; do schowka.
	;
	copy_icon_data	dd RVA copy_idata, 0x2E8, 0, 0

	copy_idata	db	0x28,	0x0,	0x0,	0x0,	0x20,	0x0,	0x0,	0x0
			db	0x40,	0x0,	0x0,	0x0,	0x1,	0x0,	0x4,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x31,	0x2D,	0x2C,	0x0,	0x96,	0x60,	0x29,	0x0
			db	0xC4,	0x9F,	0x57,	0x0,	0x38,	0x3C,	0x8F,	0x0
			db	0x97,	0x6D,	0xA9,	0x0,	0x4A,	0x92,	0xAF,	0x0
			db	0xAB,	0xA4,	0x9B,	0x0,	0xDE,	0xB3,	0x97,	0x0
			db	0xB1,	0xCE,	0xAA,	0x0,	0xE8,	0xDC,	0xAE,	0x0
			db	0x99,	0xAA,	0xDB,	0x0,	0xA0,	0xD0,	0xF4,	0x0
			db	0xC0,	0xC0,	0xC0,	0x0,	0xFE,	0xFE,	0xFE,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x5,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55
			db	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55
			db	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55
			db	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55
			db	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x55,	0x55,	0x50,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x5,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x55,	0x55,	0x58,	0xEE,	0xEE
			db	0xEE,	0xEE,	0xEE,	0xEE,	0xEE,	0x5,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x55,	0x55,	0x58,	0xFF,	0xFF
			db	0xFF,	0xFF,	0xFF,	0xFF,	0xFE,	0x5,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x55,	0x55,	0x58,	0xFF,	0xFF
			db	0xFF,	0xFF,	0xFF,	0xFF,	0xFE,	0x5,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x55,	0x55,	0x58,	0xFF,	0xFF
			db	0xFF,	0xFF,	0xFF,	0xFF,	0xFE,	0x5,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x0,	0x0,	0x8,	0xFF,	0xF5
			db	0x4C,	0x20,	0x97,	0xF,	0xFE,	0x5,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x8E,	0xEE,	0xE8,	0xFF,	0xF9
			db	0xFD,	0x8F,	0xFF,	0xFF,	0xFE,	0x5,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x8F,	0xFF,	0xF8,	0xFF,	0xF7
			db	0x0,	0xA,	0x53,	0xDF,	0xFE,	0x5,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x8F,	0xFF,	0xF8,	0xFF,	0xFF
			db	0xFF,	0xFF,	0xFF,	0xFF,	0xFE,	0x5,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x8F,	0xFF,	0xF8,	0xFF,	0xFF
			db	0xFF,	0xFF,	0xFF,	0xFF,	0xFE,	0x5,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x8F,	0xFF,	0x58,	0xFF,	0xF2
			db	0x2,	0x33,	0x70,	0xBF,	0xFE,	0x5,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x8F,	0xFF,	0x98,	0xFF,	0xFF
			db	0xFF,	0xFF,	0xFC,	0xBF,	0xFE,	0x5,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x8F,	0xFF,	0x78,	0xFF,	0xF3
			db	0x57,	0x22,	0x36,	0x5F,	0xFE,	0x5,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x8F,	0xFF,	0xF8,	0xFF,	0xFF
			db	0xFF,	0xFF,	0xFF,	0xF8,	0x0,	0x5,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x8F,	0xFF,	0xF8,	0xFF,	0xFF
			db	0xFF,	0xFF,	0xFF,	0xF8,	0xF8,	0x5,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x8F,	0xFF,	0x28,	0xFF,	0xFF
			db	0xFF,	0xFF,	0xFF,	0xF8,	0x80,	0x55,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x8F,	0xFF,	0xF8,	0x88,	0x88
			db	0x88,	0x88,	0x88,	0x88,	0x5,	0x55,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x8F,	0xFF,	0x35,	0x72,	0x23
			db	0x65,	0xFF,	0xE0,	0x55,	0x55,	0x55,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x8F,	0xFF,	0xFF,	0xFF,	0xFF
			db	0xFF,	0x80,	0x0,	0x55,	0x55,	0x55,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x8F,	0xFF,	0xFF,	0xFF,	0xFF
			db	0xFF,	0x8F,	0x80,	0x55,	0x55,	0x55,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x8F,	0xFF,	0xFF,	0xFF,	0xFF
			db	0xFF,	0x88,	0x5,	0x55,	0x55,	0x55,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x88,	0x88,	0x88,	0x88,	0x88
			db	0x88,	0x80,	0x55,	0x55,	0x55,	0x55,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55
			db	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55
			db	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55
			db	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x50
			db	0x5,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55
			db	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x55,	0x50
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
			db	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0
	align 4

	copy_icon_grp_data	dd RVA copy_icon_grp_header, 20, 0, 0

	copy_icon_grp_header	dw 0, 1, 1
				dd 0x102020, 0x40001, 0x2E8
				dw copy_icon_data.resid
	align 4

	; Dane manifestu włączonego bezpośrednio w treść pliku źródłowego.
	;
	resdata	man
		db '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
		db '<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">'
		db '<assemblyIdentity '
			db 'version="', PROG_VERSION, '" '
			db 'processorArchitecture="X86" '
			db 'name="Mikołaj Hajduk.SimPaGen" '
			db 'type="win32"'
		db '/>'
		db '<description>Prosty generator haseł.</description>'
		db '<dependency>'
			db '<dependentAssembly>'
				db '<assemblyIdentity '
					db 'type="win32" '
					db 'name="Microsoft.Windows.Common-Controls" '
					db 'version="6.0.0.0" '
					db 'processorArchitecture="X86" '
					db 'publicKeyToken="6595b64144ccf1df" '
					db 'language="*"'
				db '/>'
			db '</dependentAssembly>'
		db '</dependency>'
		db '</assembly>'
	endres
© 2007-2014, Mikołaj Hajduk