Wtyczka System

Ten dokument zgodny jest z NSIS 3.9


1. Wprowadzenie

Wtyczka System daje programistom możliwość wywoływania dowolnej wyeksportowanej funkcji z dowolnej biblioteki. Na przykład, możesz jej użyć do wywołania funkcji GetLogicalDriveStrings, aby pobrać listę dostępnych napędów na komputerze użytkownika.

Wtyczka System pozwala także na alokację, zwalnianie oraz kopiowanie pamięci; interakcję z obiektami COM oraz wykonywanie operacji matematycznych z 64 bitową precyzją.

Aby zrozumieć dobrze wtyczkę System wymagana jest wiedza z zakresu programowania.


2. Dostępne funkcje


2.1 Funkcje związane z pamięcią


Alloc

Alloc SIZE

Alokuje liczbę SIZE bajtów i zwraca adres pamięci na stos.

Przykład:

System::Alloc 64
Pop $0
DetailPrint "Zaalokowano 64 bajty w zmiennej $0"
System::Free $0

StrAlloc

StrAlloc SIZE

Alokuje bufor łańcucha znaków TCHARs o rozmiarze SIZE i zwraca adres pamięci na stos. Funkcja ta jest bardzo użyteczna, gdy chcesz napisać skrypt NSI, który działa zarówno w NSIS ANSI jak i Unicode.

Przykład:

System::StrAlloc 64 ; Bufor łańcucha znaków o długości 63 znaków i znak końca \0.
Pop $0
DetailPrint "Zaalokowano bufor łańcucha znaków o długości 64 znaki w zmiennej $0"
System::Free $0

Copy

Copy [/SIZE] DESTINATION SOURCE

Kopiuje SIZE bajtów z SOURCE do DESTINATION. Jeśli nie określono SIZE, rozmiar SOURCE będzie używało GlobalSize. Oznacza to, że jeśli nie zaalokujesz SOURCE przez użycie składni System::Alloc, System::Call lub GlobalAlloc, musisz określić SIZE. Jeśli DESTINATION jest zerem zostanie on zaalokowany i jego adres zostanie odłożony na stos.

Przykład:

# alokuje bufor i odkłada łańcuch znaków 'napis przykładowy' oraz liczbę całkowitą int w nim
System::Call "*(&t1024 'napis przykładowy', i 5) p .s"
Pop $0
# kopiuje do automatycznie utworzonego bufora
System::Copy 0 $0
Pop $1
# pobiera łańcuch znaków oraz liczbę całkowitą int z bufora $1
System::Call "*$1(&t1024 .r2, i .r3)"
# zwalnia pamięć bufora
System::Free $1
# drukuje wyniki
DetailPrint $2
DetailPrint $3
# kopiuje do naszego bufora
System::Alloc 1028
Pop $1
System::Copy $1 $0
# pobiera łańcuch znaków oraz liczbę całkowitą int z bufora $1
System::Call "*$1(&t1024 .r2, i .r3)"
# free
System::Free $0
System::Free $1
# drukuje wyniki
DetailPrint $2
DetailPrint $3

Free

Free ADDRESS

Zwalnia ADDRESS.

Przykład:

System::Alloc 64
Pop $0
DetailPrint "Zaalokowano 64 bajty w zmiennej $0"
System::Free $0

Store

Store "OPERATION [OPERATION [OPERATION ...]]"

Obsługuje operacje na stosie. Mogą to być operacje typu odłóż, zdejmij pojedynczy rejestr ze stosu NSIS lub odłożenie, zdjęcie wszystkich dostępnych rejestrów ($0-$9 oraz $R0-$R9) z odrębnego stosu wtyczki System. Operacje mogą być rozdzielone dowolnym znakiem.


Dostępne operacje:

  • Aby odłożyć $#, użyj p#, gdzie # jest cyfrą z zakresu 0..9.
  • Aby zdjąć $#, użyj r#, gdzie # jest cyfrą z zakresu 0..9.
  • Aby odłożyć $R#, użyj P#, gdzie # jest cyfrą z zakresu 0..9.
  • Aby zdjąć $R#, użyj R#, gdzie # jest cyfrą z zakresu 0..9.
  • Aby odłożyć $0-$9 oraz $R0-$R9 do odrębnego stosu wtyczki System, użyj s lub S.
  • Aby zdjąć $0-$9 oraz $R0-$R9 z odrębnego stosu wtyczki System, użyj l lub L.
  • Aby odłożyć stan flag wewnętrznych NSIS (exec_flags_t w pliku api.h) na stos, użyj F.
  • Aby zdjąć stan flag wewnętrznych NSIS (exec_flags_t w pliku api.h) ze stosu, użyj f.

Przykład:

StrCpy $0 "test"
System::Store "p0"
Pop $1
DetailPrint "$0 = $1"
StrCpy $2 "test"
System::Store "p2 R2"
DetailPrint "$2 = $R2"
StrCpy $3 "test"
System::Store "s"
StrCpy $3 "kolejny test"
System::Store "l"
DetailPrint $3
System::Store "r4" "test"
DetailPrint $4

2.2 Wywoływanie funkcji


Call PROC [( PARAMS ) [RETURN [? OPTIONS]]]
Get PROC [( PARAMS ) [RETURN [? OPTIONS]]]

Obydwa polecenia - Call jak i Get dzielą wspólną składnię. Tak jak sugerują ich nazwy, polecenie Call służy do wywoływania, zaś polecenie Get do pobierania. Cóż takiego jest wywoływane, pobierane? Zależy to od wartości PROC.


PARAMS

PARAMS jest listą parametrów. Możesz przechowywać dane w parametrach, możesz również pobierać z nich dane. Lista parametrów rozdzielana jest przecinkami. Każdy parametr składa się z trzech wartości: type, source oraz destination.

Wartość Type może być typu całkowitego, łańcuchem znaków, itp.

Wartość Source, która jest źródłem wartości parametru, może być rejestrem NSIS ($0, $1, $INSTDIR), stosem NSIS, konkretną wartością (5, "test", itp.) lub pusta (null).

Wartość Destination, która jest docelową wartością parametru po jej zwróceniu, może być rejestrem NSIS, stosem NSIS lub pusta, co oznacza, że nie wymagane jest wyjście.

Obie z tych wartości - source i destination mogą być również kropką (.), jeśli nie są potrzebne.

RETURN

RETURN jest taki jak pojedyncza definicja parametru, ale wartość source jest używana tylko wtedy, gdy tworzone są funkcje zwrotne. Zazwyczaj wartość source jest kropką.

OPTIONS

OPTIONS jest listą opcji, które kontrolują sposób zachowania wtyczki System. Każda z opcji może być wyłączona, poprzez poprzedzenie jej znakiem wykrzyknika. Na przykład: ?!e.

PARAMS, RETURN oraz OPTIONS mogą być powtarzane wielokrotnie w jednej linii Get/Call. Przy powtarzaniu, wiele może być pominięte i tylko to co chcesz zmienić może być użyte. Type, source oraz/lub destination mogą być pominięte dla każdego z parametrów, nawet dla zwracanej wartości. Opcje mogą być dodawane lub usuwane. Pozwala to na definicję prototypów funkcji i ich zapis. Ostatnie dwa przykłady pokazują taką sytuację.

PROC

PROC również może być powtarzana, ale musi być poprzedzona znakiem hash (#), poza sytuacją gdy znak hash jest poprzedzony znakiem dwukropka (shell32::#18) - w takim przypadku jest interpretowany jako liczba porządkowa funkcji.


Możliwe wartości oraz znaczenie PROC

DLL::FUNC

FUNC eksportowana z biblioteki DLL. Przykład: user32::MessageBox

::ADDR

Funkcja znajdująca się w ADDR. Przykład: zobacz poniżej

*ADDR

Struktura znajdująca się w ADDR. Przykład: zobacz poniżej

*

Nowa struktura. Przykład: zobacz poniżej

IPTR->IDX

Człon indeksowany IDX z interfejsu wskazywanego przez IPTR. Przykład: zobacz poniżej

<nic>

Nowa funkcja zwrotna. Przykład: zobacz poniżej

PROC

PROC zwrócona przez Get. Przykład: zobacz poniżej


Dostępne typy parametrów


  • v - void (ogólnie do zwracania)
  • p - pointer (wskaźnik; wskaźnik oraz inne typy o rozmiarze wskaźnika, jak uchwyty HWND)
  • b - int8, byte (liczby całkowite)
  • h - int16, short (liczbay całkowite)
  • i - int32 (liczba całkowita; zawiera typy char, byte, short i tym podobne, gdy używana jako wskaźnik)
  • l - int64, large integer (liczby całkowite)
  • m - ANSI text, string (tekst ANSI; łańcuch znaków, FYI: m - multibyte string, w - flipped over.)
  • t - text, string (tekst, łańcuch znaków; wskaźnik do pierwszego znaku). np. TCHAR*, który jest łańcuchem znaków Unicode w NSIS Unicode.
  • w - WCHAR text (tekst WCHAR, łańcuch znaków Unicode)
  • g - GUID
  • k - callback (funkcja zwrotna)
  • @ - Bezpośredni dostęp rejestru do pamięci (bufor ograniczony jest do (NSIS_MAX_STRLEN - 21) * NSIS_CHAR_SIZE bajtów)
  • &vN - wypełnienie N bajtów (tylko struktury)
  • &iN - całkowita liczba N bajtów (tylko struktury)
  • &l - rozmiar struktury (tylko struktury)
  • &tN - tablica N znaków tekstowych TCHAR (tylko struktury)
  • &mN - tablica N znaków tekstowych ANSI CHAR (tylko struktury)
  • &wN - tablica N znaków Unicode WCHAR (tylko struktury)
  • &g16 - 16 bajtów GUID (tylko struktury)

Dodatkowo, każdy z typów (poza b, h, k oraz @) może być poprzedzony znakiem gwiazdki, żeby oznaczyć wskaźnik. Używając gwiazdki, wtyczka System wymaga raczej podania wartości parametru, niż adresu wskaźnika. Aby podać bezpośredni adres, użyj p, bez gwiazdki. Dostępny jest przykład. Funkcja Alloc zwraca adres i ta zwracana wartość powinna być użyta z p, bez gwiazdki.


Dostępne wartości Sources oraz Destinations


  • . - ignorowane
  • number (liczba) - konkretna wartość w postaci szesnastkowej, dziesiętnej, ósemkowej lub całkowitej. Kilka liczb całkowitych rozdzielamy symbolem (|)
  • 'string', "string", `string` (łańcuch znaków) - Konkretna wartość łańcucha znaków
  • r0 - r9 - $0 do $9
  • r10 - r19
    R0 - R9
    - $R0 do $R9
  • c - $CMDLINE
  • d - $INSTDIR
  • o - $OUTDIR
  • e - $EXEDIR
  • a - $LANGUAGE
  • s - Stos NSIS
  • n - pusty dla source, nie wymagane jest wyjście dla destination

Źródło Source jest wymagane, gdy używany jest typ @ i musi być rejestrem. Gdy wywołanie zwraca rejestr źródła source, zawiera już adres pamięci w postaci łańcucha znaków, więc użycie destination nie jest potrzebne.


Funkcje zwrotne


Funkcje zwrotne są normalnymi funkcjami, które są przekazywane do funkcji i wywoływane przez nią. Używane są one często do podawania możliwie dużego zbioru danych, element po elemencie. Na przykład, EnumChildWindows używa funkcji zwrotnej. Jako że, funkcje NSIS niezupełnie są zwykłymi funkcjami, wtyczka System wprowadza własny mechanizm do obsługi funkcji zwrotnych. Pozwala on na tworzenie funkcji zwrotnych i uzyskiwanie informacji o każdym wywołaniu tych funkcji.

Tworzenie funkcji zwrotnych realizowane jest przez użycie Get oraz składni tworzenia funkcji zwrotnych. Jeśli nie wywołujesz samodzielnie funkcji zwrotnych, źródło source parametrów powinno być pomijane poprzez użycie znaku kropki. Wywołując funkcję zwrotną, destination parametrów zostanie wypełniony wartościami podanymi funkcji zwrotnej. Zwracana wartość funkcji zwrotnej jest ustalana przez źródło zwracanego "parametru". Source zwracanego "parametru" zawsze powinien być ustawiany jak System powiadomi, że funkcja zwrotna została wywołana.

System::Get "(i .r0, i .r1) iss"

Aby podać funkcję zwrotną do funkcji, użyj typu k.

System::Get "(i .r0, i .r1) isR0"
Pop $0
System::Call "dll::UseCallback(k r0)"

Za każdym razem, gdy wywoływana jest funkcja zwrotna, ciag znaków callback#, gdzie # jest ilością funkcji zwrotnych, zostanie umieszczony w destination zwracanego "parametru". Pierwsza utworzona funkcja zwrotna równa jest 1, druga to 2, trzecia to 3 i tak dalej. Jako, że System jest pojedynczym wątkiem, funkcja zwrotna może być wywołana tylko podczas wywoływania innej funkcji. Na przykład, funkcja zwrotna EnumChildWindows może być wywołana tylko wtedy, gdy wywoływana jest funkcja EnumChildWindows. Powinieneś więc sprawdzać callback# po wywołaniu kazdej funkcji, która może wywołać twoją funkcję zwrotną.

System::Get "(i .r0, i .r1) isR0"
Pop $0
System::Call "dll::UseCallback(k r0)"
StrCmp $R0 "callback1" 0 +2
DetailPrint "UseCallback podaje ($0, $1) do funkcji zwrotnej"

Po wywołaniu funkcji zwrotnej, powinieneś użyć funkcji Call, przypisując ją do wartości zwracanej przez Get - funkcję zwrotną. Mówi to wtyczce System, aby zwrócił wartość z funkcji zwrotnej. Destination zwracanego "parametru" musi zostać wyczyszczony przed wywołaniem funkcji, aby uniknąć fałszywej detekcji wywołań funkcji zwrotnych. Jeśli określiłeś source dla zwracanego "parametru", po utworzeniu funkcji zwrotnej, powinieneś zapełnić source odpowiednią zwracaną wartością. Funkcje zwrotne nie są automatycznie zwalniane, więc pamiętaj o tym po zakończeniu ich używania.

System::Get "(i .r0, i .r1) isR0"
Pop $0
System::Call "dll::UseCallback(k r0)"
loop:
	StrCmp $R0 "callback1" 0 done
	DetailPrint "UseCallback podaje ($0, $1) do funkcji zwrotnej"
	Push 1 # zwracana wartość funkcji zwrotnej
	StrCpy $R0 "" # czyści $R0, jeśli nie wywołuje się już więcej funkcji zwrotnych
	System::Call $0 # mówi systemowi, aby zwrócił wartość z funkcji zwrotnej
	Goto loop
done:
System::Free $0

Kompletny przykład dostępny jest w sekcji z przykładami.


Uwagi

  • Aby dowiedzieć się jaki jest indeks członu interfejsu COM, musisz poszukać definicji tego interfejsu COM w plikach nagłówkowych, które rozprowadzane są z Visual C/C++ lub Platform SDK. Indeksowanie zaczyna się od zera.
  • Jeśli funkcja nie może być znaleziona lub użyto parametru o typie 't', do jej nazwy zostanie dodana litera A lub W i ponownie zostanie wyszukiwana. Procedura taka miejsce, ponieważ wiele funkcji Windows API ma dwie wersje, jedna dla łańcuchów znaków ANSI i druga dla łańcuchów znaków Unicode. Wersja ANSI jest oznaczona literką A, wersja Unicode zaś literką W. Na przykład: lstrcpyA oraz lstrcpyW.
  • Biblioteki dynamiczne znajdujące się w katalogu system32 mogą być ładowane bez podania ścieżki dostępu. Wszystkie inne biblioteki powinny być ładowane jako pełne ścieżki dostępu w cudzysłowie.

Dostępne opcje

  • c

    konwencja wywoływania cdecl (stos przywracany przez wywołującego). Domyślnie, na maszynach x86, używana jest konwencja wywoływania stdcall (stos przywracany przez callee).

  • r

    Zawsze zwraca (dla GET oznacza to, że powinieneś zdjąć result (wynik) oraz proc, dla CALL oznacza to, że powinieneś zdjąć result (przynajmniej)). Domyślnie wynik zwracany jest tylko przy wystąpieniu błędów (dla GET zdejmujesz wyniki błędów jak i proc, a dla CALL zdejmiesz zwracaną wartość lub wynik w zdefiniowanym miejscu zwracanej wartości).

  • n

    Brak przedefiniowań. Zawsze gdy tego użyjesz, nie bedzie nigdy przedefiniowywany zarówno przez GET jak i CALL. Opcja ta nigdy nie jest dziedziczona przez potomków.

  • s

    Użyj ogólnego stosu (Stack). Jeśli pierwsza funkcja zwrotna jest zdefiniowana system zaczyna używać tymczasowego stosu dla wywołań funkcji.

  • e

    Wywołaj GetLastError() po zakończeniu procedury i umieść wynik na stosie.

  • u

    Wyładuj bibliotekę DLL po wywołaniu (używając FreeLibrary, będziesz mógł np. dokonać operacji usunięcia).

  • 2

    Eksperymentalna składnia v2.


Eksperymentalna składnia v2

  • Typy struktur pisane wielkimi literami są dostosowane do ich naturalnego wyrównania. Typy pisane małymi literami są pakowane bez wyrównania.

  • ID funkcji zwrotnej Callback id oparte jest na zaalokowanej funkcji zwrotnej


Przykłady

System::Call "user32::MessageBox(p $HWNDPARENT, t 'Wtyczka NSIS - System', t 'Test', i 0)"
System::Call '"$SysDir\MyLibrary.dll"::MyFunction(i 42)'
System::Call "kernel32::GetModuleHandle(t 'user32.dll') p .s"
System::Call "kernel32::GetProcAddress(p s, m 'MessageBoxA') p .r0"
System::Call "::$0(p $HWNDPARENT, m 'GetProcAddress test', m 'Wtyczka NSIS - System', i 0)"
System::Get "user32::MessageBox(p $HWNDPARENT, t 'To jest domyślny tekst', t 'Domyślny', i 0)"
Pop $0
System::Call "$0"
System::Get "user32::MessageBox(p $HWNDPARENT, t 'To jest domyślny tekst', \
	t 'Domyślny', i 0x1|0x10)"
Pop $0
System::Call "$0(, 'To jest test System::Get', 'Wtyczka NSIS - System',)"
System::Call "advapi32::GetUserName(t .r0, *i ${NSIS_MAX_STRLEN} r1) i.r2"
DetailPrint "Nazwa użytkownika - $0"
DetailPrint "Długość łańcucha znaków - $1"
DetailPrint "Zwracana wartość - $2"
System::Alloc 4
Pop $0
System::Call "*$0(i 5)" ; Zapis
System::Call "*$0(i .r1)" ; Odczyt
System::Free $0
DetailPrint $1
System::Call "*(i 5) p .r0"
System::Call "*$0(i .r1)"
System::Free $0
DetailPrint $1

System::Call '*0(p, &l.r2, &t2)' ; &l. nie jest częścią struktury
DetailPrint "Struct size=$2"


System::Call '*(&l4,i,i,i,i,&t128)p.r1' ; Wypełnia funkcję dwOSVersionInfoSize rozmiarem struktury int32
${If} $1 Z<> 0
	System::Call 'kernel32::GetVersionEx(pr1)i.r0'
	System::Call '*$1(i,i.R1,i.R2,i.R3)'
	System::Free $1
	${IfThen} $0 <> 0 ${|} DetailPrint "v$R1.$R2.$R3" ${|}
${EndIf}
System::Call "user32::GetClientRect(p $hwndparent, @ r0)"
System::Call "*$0(i,i,i.r1,i.r2)"
DetailPrint ClientRect=$1x$2
# definicje
!define CLSCTX_INPROC_SERVER 1
!define CLSID_ActiveDesktop {75048700-EF1F-11D0-9888-006097DEACF9}
!define IID_IActiveDesktop {F490EB00-1240-11D1-9888-006097DEACF9}
# utwórz interfejs IActiveDesktop
System::Call "ole32::CoCreateInstance( \
	g '${CLSID_ActiveDesktop}', p 0, \
	i ${CLSCTX_INPROC_SERVER}, \
	g '${IID_IActiveDesktop}', *p .r0) i.r1"
StrCmp $1 0 0 end
# wywołaj IActiveDesktop->GetWallpaper
System::Call "$0->4(w .r2, i ${NSIS_MAX_STRLEN}, i 0)"
# wywołaj IActiveDesktop->Release
System::Call "$0->2()"
# wydruk wyników
DetailPrint $2
end:
InitPluginsDir
File "/oname=$PLUGINSDIR\MyDLL.dll" MyDLL.dll
System::Call 'KERNEL32::AddDllDirectory(w "$PLUGINSDIR")'
System::Call 'KERNEL32::LoadLibrary(t "$PLUGINSDIR\MyDLL.dll")p.r1'
System::Call 'MyDLL::MyFunc(i 5) ? u'
System::Call 'KERNEL32::FreeLibrary(pr1)'
Delete $PLUGINSDIR\MyDLL.dll
System::Get "(p.r1, p) iss"
Pop $R0
System::Call "user32::EnumChildWindows(p $HWNDPARENT, k R0, p) i.s"
loop:
	Pop $0
	StrCmp $0 "callback1" 0 done
	System::Call "user32::GetWindowText(pr1,t.r2,i${NSIS_MAX_STRLEN})"
	System::Call "user32::GetClassName(pr1,t.r3,i${NSIS_MAX_STRLEN})"
	IntFmt $1 "0x%X" $1
	DetailPrint "$1 - [$3] $2"
	Push 1 # zwracana wartość funkcji zwrotnej
	System::Call "$R0"
	Goto loop
done:
System::Free $R0
DetailPrint "Funckja EnumChildWindows zwróciła $0"
System::Get '(m.r1)ir2r0 ?2' ; składnia v2
Pop $9
System::Call 'kernel32::EnumSystemLocalesA(k r9, i 0)'
loop:
	StrCmp $0 "callback$9" 0 done
	DetailPrint "Locale: $1"
	StrCpy $2 1 ; zwracana wartość funkcji EnumLocalesProc
	System::Call $9 ; wynik funkcji EnumLocalesProc
	Goto loop
done:
System::Free $9
System::Call '*(&t50 "!")p.r2' ; DecimalSep
System::Call '*(&t50 "`")p.r3' ; ThousandSep
System::Call '*(i 2, i 0, i 3, P r2, P r3, i 1)p.r1 ?2'
System::Call 'kernel32::GetNumberFormat(i 0, i 0, t "1337.666" r4, p r1, t.r5, i ${NSIS_MAX_STRLEN})'
DetailPrint "Formatowanie użytkownika $4: $5"
System::Free $3
System::Free $2
System::Free $1
!define MB "user32::MessageBox(p$HWNDPARENT,t,t'Wtyczka NSIS - System',i0)"
System::Call "${MB}(,'mój komunikat',,)"
System::Call "${MB}(,'inny komunikat',,) i.r0"
MessageBox MB_OK "Ostatnie wywołanie zwróciło $0"
System::Call "user32::SendMessage(p $HWNDPARENT, t 'test', t 'test', p 0) p.s ? \
	e (,t'Test zamieniania',,) i.r0 ? !e #user32::MessageBox"
DetailPrint $0
ClearErrors
Pop $0
IfErrors good
MessageBox MB_OK "To okno z komunikatem nie zostanie wyświetlone"
good:

2.3 Funkcje 64-bitowe

Int64Op ARG1 OP [ARG2]

Wykonuje OP na ARG1 i opcjonalnie ARG2 oraz zwraca wynik na stosie. Zarówno ARG1 jak i ARG2 są 64-bitowymi liczbami całkowitymi. Oznacza to, że mogą one operować w zakresie pomiędzy -2^63 a 2^63 - 1.


Dostępne operacje


  • Addition (Dodanie) -- +
  • Subtraction (Odejmowanie) -- -
  • Multiplication (Mnożenie) -- *
  • Division (Dzielenie) -- /
  • Modulo (Reszta z dzielenia) -- %
  • Shift left (Przesunięcie w lewo) -- <<
  • Arithmetic shift right (arytmetyczne przesunięcie w prawo) -- >>
  • Logical shift right (logiczne przesunięcie w prawo) -- >>>
  • Bitowe or -- |
  • Bitowe and -- &
  • Bitowe Xor -- ^
  • Bitowe not (jeden argument) -- ~
  • Logiczne not (jeden argument) -- !
  • Logiczne or -- ||
  • Logiczne and -- &&
  • Mniejsze od -- <
  • Równe -- =
  • Większe niż -- >

Przykłady

System::Int64Op 5 + 5
Pop $0
DetailPrint "5 + 5 = $0" # 10
System::Int64Op 526355 * 1565487
Pop $0
DetailPrint "526355 * 1565487 = $0" # 824001909885
System::Int64Op 5498449498849818 / 3
Pop $0
DetailPrint "5498449498849818 / 3 = $0" # 1832816499616606
System::Int64Op 0x89498A198E4566C % 157
Pop $0
DetailPrint "0x89498A198E4566C % 157 = $0" # 118
System::Int64Op 1 << 62
Pop $0
DetailPrint "1 << 62 = $0" # 4611686018427387904
System::Int64Op 0x4000000000000000 >> 62
Pop $0
DetailPrint "0x4000000000000000 >> 62 = $0" # 1
System::Int64Op 0x8000000000000000 >> 1
Pop $0
DetailPrint "0x8000000000000000 >> 1 = $0" # -4611686018427387904 (0xC000000000000000)
System::Int64Op 0x8000000000000000 >>> 1
Pop $0
DetailPrint "0x8000000000000000 >>> 1 = $0" # 4611686018427387904 (0x4000000000000000)
System::Int64Op 0x12345678 & 0xF0F0F0F0
Pop $0
# Operacja IntFmt jest 32-bitowa, to tylko przykład
IntFmt $0 "0x%X" $0
DetailPrint "0x12345678 & 0xF0F0F0F0 = $0" # 0x10305070
System::Int64Op 1 ^ 0
Pop $0
DetailPrint "1 ^ 0 = $0" # 1
System::Int64Op 1 || 0
Pop $0
DetailPrint "1 || 0 = $0" # 1
System::Int64Op 1 && 0
Pop $0
DetailPrint "1 && 0 = $0" # 0
System::Int64Op 9302157012375 < 570197509190760
Pop $0
DetailPrint "9302157012375 < 570197509190760 = $0" # 1
System::Int64Op 5168 > 89873
Pop $0
DetailPrint "5168 > 89873 = $0" # 0
System::Int64Op 189189 = 189189
Pop $0
DetailPrint "189189 = 189189 = $0" # 1
System::Int64Op 156545668489 ~
Pop $0
DetailPrint "156545668489 ~ = $0" # -156545668490
System::Int64Op 1 !
Pop $0
DetailPrint "1 ! = $0" # 0

3. FAQ


Pytanie:

Jak mogę przypisać struktury do funkcji?


Odpowiedź:

Przede wszystkim, musisz zaalokować strukturę. Możesz to zrobić na dwa sposoby. Możesz użyć polecenia Alloc lub Call ze specjalną składnią alokowania struktury. Następnie, jeśli chcesz przypisać dane do struktury, musisz wypełnić ją danymi. Gdy to zrobisz, wywołaj funkcję z wskaźnikiem na strukturę. Na koniec, jeśli chcesz odczytac dane ze struktury, które mogły zostac tam zapisane przez wywołaną funkcję, musisz użyć polecenia Call ze składnią obsługujacą struktury. Gdy wszystko już zostanie zrobione, pamiętaj o zwolnieniu struktury.


Alokacja


Aby zaalokować strukturę, używając polecenia Alloc, musisz znać rozmiar struktury w bajtach. Dlatego też, łatwiej będzie użyć polecenia Call. W takim przypadku łatwo zobaczyć, że wymagany rozmiar to 16 bajtów, ale inne przypadki nie muszą byc tak proste. W obu przypadkach, adres struktury zostanie ulokowany na górze stosu i powinien byc stamtąd zdjęty przy użyciu polecenia Pop.

System::Alloc 16
System::Call "*(i, i, i, t)p.s"

Ustawianie danych


Ustawianie danych można przeprowadzić używając polecenia Call. Można to zrobić w fazie alokowania, lub innej używając składni obsługującej struktury.

System::Call "*(i 5, i 2, i 513, t 'test')p.s"
# adres pamięci struktury przechowywany jest w $0
System::Call "*$0(i 5, i 2, i 513, t 'test')"

Przekazywanie funkcji


Wszystkie metody alokacji zwracają adres, typ wprowadzanych danych powinien być liczbą całkowitą, adresem w pamięci.

# adres pamięci struktury przechowywany jest w $0
System::Call "dll::func(p r0)"

Odczyt danych


Odczyt danych ze struktury odbywa się przy użyciu tej samej składni co ich ustawianie. Jedyną różnicą jest to, że część destination parametru zostanie ustawiona, zaś część source zostanie pominięta poprzez użycie kropki.

# adres pamięci struktury przechowywany jest w $0
System::Call "*$0(i .r0, i .r1, i .r2, t .r3)"
DetailPrint "pierwszy int = $0"
DetailPrint "drugi int = $1"
DetailPrint "trzeci int = $2"
DetailPrint "łańcuch znaków = $3"

Zwalnianie pamięci


Pamięć jest zwalniana przy użyciu polecenia Free.

# adres pamięci struktury przechowywany jest w $0
System::Free $0

Pełny przykład


# alokacja
System::Call "*(i,i,p,p,p,p,p,p)p.r1"
# wywołanie
System::Call "Kernel32::GlobalMemoryStatus(p r1)"
# pobranie
System::Call "*$1(i.r2, i.r3, p.r4, p.r5, p.r6, p.r7, p.r8, p.r9)"
# zwolnienie
System::Free $1
# wydruk danych
DetailPrint "Rozmiar struktury: $2 bajtów"
DetailPrint "Używana pamięć: $3%"
DetailPrint "Całkowity rozmiar pamięci fizycznej: $4 bajtów"
DetailPrint "Wolnej pamięci fizycznej: $5 bajtów"
DetailPrint "Całkowity rozmiar pliku stronicowania: $6 bajtów"
DetailPrint "Wolnego w pliku stronicowania: $7 bajtów"
DetailPrint "Całkowity rozmiar pamięci wirtualnej: $8 bajtów"
DetailPrint "Wolnej pamięci wirtualnej: $9 bajtów"

4. Autorzy

Copyright © 2002 brainsucker (Nik Medved)

Copyright © 2002 - 2024 Współtwórcy NSIS