A cikk melléklete két projektet tartalmaz. A PwdHolder alkalmazás Form-ja egy beviteli mezőt tartalmaz, mely jelszókét tárolja a beírt szöveget. Ezt fogjuk a másik alkalmazás segítségével kiolvasni.
A PwdViewer alkalmazásban egy csokor API függvényt használunk fel egy tetszőleges alkalmazás szövegbeviteli mezőjének kiolvasására, jelen esetben a másik program mezőjének értelmezésére. A műveletben kétféle eljárást alkalmazunk.
Az első eljárásban a SendMessage függvény segítéségével oldjuk meg a problémát, míg a másikban a GetDlgItemText függvény lesz a kulcs a megoldáshoz. A két metódus eltérő módon működik.
A két metódus meghívását azonban minden esetben megelőzi a cél beviteli mező megkeresésének folyamata. A program elindítása után elindítunk egy időzítőt, mely egytized másodpercenként figyeli a kurzor aktuális pozícióját, és meghatározza az adott pozícióban megtalálható vezérlő azonosítóját. Az azonosítót pedig már mindkét megoldásban felhasználhatjuk.
A példánkban a Win32 osztályban helyeztük el a szükséges API függvények, konstansok és struktúra definícióját. Az egérmutató aktuális helyzetét tároló struktúránk az APIPoint nevet viseli.
public struct APIPoint
{
public int x;
public int y;
}
A SendMessage függvény úgy kérdezi le a kívánt értéket, hogy egy WM_GETTEXT üzenetet küld el a kiválasztott ablaknak. A konstans értéke a következő:
public const int WM_GETTEXT = 0x000D;
Vizsgáljuk meg, hogyan történik az adott vezérlő kiválasztása a mutató segítségével. A műveletet a GetWindow metódusba ágyaztuk, mely két OUT módú paraméterrel rendelkezik: az első visszaadja a célvezérlő osztályát, a második pedig a globális azonosítóját.
private void GetWindow(out string classstr, out int hWnd)
{
Példányosítjuk pozíció koordinátáit tartalmazó struktúrát.
Win32.APIPoint p = new Win32.APIPoint();
A GetCursorPos API függvény meghívásával ebben a struktúrában tárolhatjuk el a koordinátákat.
Win32.GetCursorPos(out p);
A koordináták alapján meghatározzuk az aktuális pozícióban megtalálható ablak Handle property-jét. Ehhez a WindowFromPoint függvényt hívjuk meg.
int h = Win32.WindowFromPoint(p.x,p.y);
Az osztály meghatározásához egy StringBuilder objektumot adunk át a GetClassName API függvénynek, melynek ez egy OUT paramétere lesz.
StringBuilder builder = new StringBuilder(256);
Win32.GetClassName(h,builder,builder.Capacity);
A kapott értékeket végül átadjuk értékként a kimenő paramétereknek.
classstr = builder.ToString();
hWnd = h;
}
SendMessage függvény meghívása
Az első megoldásban tehát a kapott értékekkel meghívjuk a SendMessage API függvényt.
string c = "";
int hWnd = 0;
GetWindow(out c, out hWnd);
textBox1.Text = c;
A kapott ablakkezelő értékét használjuk fel a SendMessage függvény első paramétereként. A második paraméter tartalmazza az üzenetet, melyet most a Win32.WM_GETTEXT konstans tartalmaz. A harmadik paraméter egy számot tartalmaz, mely a lekérdezendő szöveget tartalmazó puffer méretét adja meg, míg a negyedik paraméter egy mutató a pufferre.
A karakterláncot mutatóvá konvertáljuk a StrToPtr metódusunk segítségével.
IntPtr ptr = StrToPtr(s);
Win32.SendMessage(hWnd,Win32.WM_GETTEXT,100,ptr.ToInt32());
A függvényhívás után a pointer által mutatott memóriaterületen elhelyezett értéket kinyerjük.
string outstr = Marshal.PtrToStringAnsi(ptr);
GetDlgItemText függvény meghívása
A függvényhívás itt abban különbözik az előzőtől, hogy szükségünk van a vezérlőt tartalmazó ablak kezelőjének meghatározására. Ehhez meghívjuk a GetParent API függvényt.
parentWnd = Win32.GetParent(hWnd);
Meghatározzuk a vezérlő ID-jét is a kezelőjéből a GetDlgItemID függvénnyel.
int id = Win32.GetDlgCtrlID(hWnd);
A függvény első paraméterében helyezzük el a szülőablak kezelőjét, a másodikban a vezérlő azonosítóját.
Win32.GetDlgItemText(parentWnd,id,ptr.ToInt32(),100);
A kapott pointer mutatta memóriaterületet hasonló módon olvassuk ki.
string outstr = Marshal.PtrToStringAnsi(ptr);
Látható, hogy bármely megoldást használjuk, kinyerhető az esetleg elfelejtett jelszó a beviteli mezőből.