Posts tagged ‘Windows’

Gdzie jest pasek zadań

2009-08-10 15:11

Programy działające w tle (np. komunikatory) często używają różnego rodzaju “wyskakujących” powiadomień, które w założeniu mają pojawiać się tuż obok zasobnika systemowego (system tray), gdzie wspomniane programy mają swoje ikonki. W rzeczywistości pozycja tych komunikatów jest często hardcode‘owana w okolicach prawego dolnego rogu ekranu. Jeśli więc użytkownik przypadkiem ma pasek zadań gdzie indziej, to wtedy cały misterny plan idzie w… las ;]
Dlatego lepszym rozwiązaniem jest sprawdzanie, gdzie tak naprawdę ów pasek się znajduje. Przez długi czas można było to zrobić poprzez zwyczajne pobranie jego uchwytu (HWND) i odczytanie wymiarów tak, jak każdego innego okna – np. przez GetWindowRect:

  1. HWND hTaskBar = FindWindow(TEXT("Shell_TrayWnd"), NULL);
  2. // "Shell_TrayWnd" to klasa okna specyficzna dla paska zadań
  3. RECT rc; GetWindowRect (hTaskBar, &rc);

Począwszy od Windows Vista nie jest to jednak możliwe, gdyż ze względu na bezpieczeństwo (tzw. izolacja sesji 0) nie da się już tak po prostu pobrać uchwytu do paska zadań ze zwykłej aplikacji. Istnieje na szczęście przenośny sposób na pobranie jego pozycji; w tym celu trzeba się posłużyć funkcją powłoki systemowej SHAppBarMessage (z nagłówka shellapi.h i biblioteki shellapi.lib):

  1. UINT GetTaskBarPos(LPRECT rc)
  2. {
  3.     APPBARDATA abd = { sizeof(APPBARDATA), NULL };
  4.     if (!SHAppBarMessage(ABM_GETTASKBARPOS, &abd)) return 0;
  5.     if (rc) memcpy (rc, &abd.rc, sizeof(RECT));
  6.     return abd.uEdge;
  7. }

Tak możemy otrzymać nie tylko wymiary prostokąta okalającego pasek, ale też informację o tym, przy której krawędzi się on znajduje. Jest ona zawarta w polu uEdge struktury zwracanej przez funkcję SHAppBarMessage i równa którejś ze stałych ABE_BOTTOM, ABE_TOP, itd.

Mając te dwie informacje możemy nie tylko wyświetlać nasze powiadomienia w odpowiednim miejscu, ale też zapewnić, żeby w razie ich nagromadzenia “rosły” one w odpowiednim kierunku.

Tags: ,
Author: Xion, posted under Programming » 10 comments

Rootkity i inne nieszczęścia

2008-12-05 11:42

Jedną z rzeczy, którą musiałem wykonać w trakcie (tymczasowej) przesiadki na komputer stacjonarny, było dogłębne sprawdzenie go programem antywirusowym – co “z pewnych względów” nie było czynione przez dobrych kilka miesięcy :) Skan nie wykrył aczkolwiek w zasadzie nic bardziej niebezpiecznego niż typowe ‘śledzące ciasteczka’ (tracking cookie). Dopiero później zaczęło się robić ciekawie.
Zło (i to przez duże Z) zostało bowiem wkrótce wykryte przez skaner działający w tle, który zidentyfikował je heurystycznie jako rootkit i oprócz tej informacji nie powiedział zresztą nic więcej. Przyznam, że było to moje pierwsze zetknięcie z tego typu szkodnikami, więc tym bardziej energicznie zabrałem się do rozwiązywania problemu – zwłaszcza że ze wszystkich typów złośliwego oprogramowania to właśnie rootkity sa zdecydowanie najgroźniejsze.
Na szczęście ten okazał się dość znanym i nawet nieszczególnie niebezpiecznym drobnoustrojem, przenoszącym się – o dziwo – nie przez sieć, lecz przez dyski wymienne. Zapewne dlatego też moje kilkugodzinne starcie z przeciwnikiem zakończyło się (prawdopodobnie) sukcesem, zaś wnioski z tego są następujące:

  • Antywirusy nie radzą sobie z rootkitami i zwykle potrafią jedynie zasygnalizować, że w systemie “coś siedzi”. Do wykrywania rootkitów istnieją dedykowane programy, których najlepiej jest używać grupowo, a i tak pozytywnym wynikom nie należy do końca ufać.
  • Google pomaga :) Jedną z dobrych metod identyfikacji niechcianych programów jest bowiem przejrzenie listy procesów (stworzonej przez narzędzie w rodzaju IceSword) i kolejne sprawdzenie wszystkich potencjalnie podejrzanych pozycji poprzez wyszukanie informacji na ich temat w Internecie.
  • Najbardziej znanym narzędziem do usuwania rootkitów jest ComboFix, który pomógł zresztą w moim przypadku. W ogólności jednak naprawa może być niemożliwa. Tak naprawdę zaleca się zresztą, by po wykryciu rootkita poważnie zastanowić nad sformatowaniem dysku i odbudową systemu od podstaw. Brr :)

Krótko mówiąc, wykrywanie i walka z tym rodzajem szkodliwego oprogramowania to coś znacznie poważniejszego niż wciśnięcie przycisku Scan i czekanie na wyniki :] Rezultaty też nigdy nie są pewne.

O reinstalacji systemu na komputerze stacjonarnym trzeba więc będzie pomyśleć jak najszybciej, a od wczoraj stało się to prostsze, gdyż mój laptop wrócił z naprawy. Okazało się, że konieczna była wymiana płyty głównej (!) – oryginalna prawdopodobnie miała fabryczną usterkę… No cóż, dobrą stroną jest to, że za tę skomplikowaną operację nie musiałem zapłacić ani grosza; niech żyją gwarancje :)

Tags:
Author: Xion, posted under Applications, Life » 11 comments

Więcej Schowka

2008-10-26 15:03

Wiele różnych rozbudowanych programów – jak np. IDE lub pakiety biurowe – zawiera mechanizmy rozszerzające funkcjonalność windowsowego Schowka. Oznacza to najczęściej możliwość zachowania więcej niż jednego wycinka naraz i przełączanie się między nimi, gdy chcemy wkleić gdzieś któryś z nich.
Dotąd nie byłem zbyt entuzjastycznie nastawiony do takiej funkcjonalności – może dlatego, że posiadanie więcej niż jednego Schowka było poza zasięgiem moich możliwości pojmowania ;) Zdarzyło się jednak, że kilka razy potrzebowałem wrócić do tekstu, który już “nieopatrznie” nadpisałem kilkoma kolejnymi skopiowaniami do Schowka. Wtedy też zacząłem rozglądać się za aplikacją, która w jakiś sensowny sposób rozszerza możliwości systemowego Schowka, dodając do niego więcej ‘slotów’.

Poszukiwania nie były niestety specjalnie owocne. Najlepsze, co udało mi się znaleźć, to program o wielce oryginalnej nazwie MultiClipBoard. Narzędzie to chowa się do systemowego zasobnika i pozwala posiadać nieograniczoną liczbę niezależnych Schowków na wycinaną treść. Potrafi też tworzyć nowy przy każdym kopiowaniu, dzięki czemu niczego nie zgubimy. Niestety, nie oferuje zbyt wielu przydatnych skrótów klawiszowych, umożliwiających chociażby cofnięcie się do poprzednio wyciętego elementu.
Ale oczywiście lepsze to niż nic – przynajmniej na razie. Bo kto wie, może w Windows 7 zamiast kolejnych wodotrysków zobaczymy coś użytecznego, jak właśnie nieco bardziej inteligentną obsługę Schowka. Chociaż to pewnie tylko pobożne życzenia :)

Tags: ,
Author: Xion, posted under Applications » 4 comments

Używanie nagłówków Windows

2008-08-22 13:21

Chociaż Windows API ciągnie za sobą skutki kilkunastu lat wstecznej kompatybilności, nie znaczy to, że nie pojawiają się tam nowe możliwości. Ponieważ jednak wszystkie funkcje są importowane z DLL-i w sposób statyczny, nie jest możliwe, by każda nowsza była dostępna automatycznie. W przeciwnym wypadku program, który faktycznie działałby bez problemu np. na Windows 98 wymagałby w praktyce najnowszej wersji systemu – mimo tego, że nie korzysta z żadnej nowej funkcjonalności.
Niekiedy jednak nie chcemy ograniczać się do “wspólnego mianownika” wszystkich aktualnie obsługiwanych wersji Windows i chcemy użyć czegoś, co rzeczywiście jest dostępne począwszy od jakiejś nowszej edycji systemu. Co wtedy zrobić?

W dokumentacji (czyli MSDN) jest na szczęście dokładnie zaznaczone to, w której wersji Windows wprowadzoną daną funkcję czy strukturę. Ale żeby odpowiedni symbol został włączony do kompilacji i linkowania, należy jeszcze przed dołączeniem windowsowego nagłówka (zazwyczaj windows.h) zdefiniować odpowiednie makro.
A właściwie to nawet więcej niż jedno, jako że MSDN wspomina o czterech. Są to:

  • WINVER i _WIN32_WINNT, wskazujące na liczbową wersję systemu. Wartość 0x0502 oznacza na przykład wersję 5.1, czyli Windows XP z SP2.
  • _WIN32_IE, mające zawierać docelową wymaganą wersję Internet Explorera
  • NTDDI_VERSION, ustawialne na którąś z predefiniowanych stałych przypisanych każdej większej edycji Windows (np. NTDDI_WINXPSP1 lub NTDDI_WIN2K)

Pierwsze trzy są już uważane za przestarzałe i aktualnie używać należy NTDDI_VERSION, które jest zresztą znacznie wygodniejsze. W praktyce dobrze jest jednak ustawiać wszystkie makra, zwłaszcza jeśli nasz kod może być potencjalnie kompilowany na wielu różnych wersjach Platform SDK. I tak na przykład jeśli chcemy wykorzystać pule wątków (thread pools) dostępne począwszy od Windows Vista, powinniśmy dodać taki oto kod:

  1. #define NTDDI_VERSION NTDDI_VISTA
  2. #define WINVER 0x0600
  3. #define _WIN32_WINNT 0x0600
  4. #include <windows.h>

Po wartości makr odpowiadające wszystkim edycjom Windows należy udać do MSDN, do sekcji:

Win32 and COM Development > Development Guides > Windows API > Using Windows Headers

Tags: ,
Author: Xion, posted under Programming » 1 comment

Przerwa na komunikaty Windows

2008-07-23 17:05

W Windows obsługa zdarzeń opiera się na koncepcji pętli komunikatów (message loop). Taka pętla powinna nieustannie kręcić się w każdym wątku, w którym tworzone są okna, i na bieżąco pobierać pojawiające się komunikaty o zdarzeniach. Dzięki temu użytkownik może przeprowadzać interakcje z interfejsem programu. Dlatego też wszelkie dłuższe działania (np. złożone obliczenia lub odczyt/zapis, zwłaszcza przez sieć) mogą sprawić, że aplikacja wyda się zawieszona. Pętla komunikatów nie będzie bowiem pobierać i przetwarzać gromadzących się w kolejce zdarzeń.
Typowym rozwiązaniem jest umieszczenie takich czasochłonnych operacji w osobnym wątku. Czasem jest to oczywiście niezbędne, lecz wielowątkowość, jak wiadomo, oprócz korzyści wprowadza dodatkowe problemy, które należy uwzględnić – jak choćby synchronizacja dostępu do danych.

Jeśli jednak nasza długa operacja daje się podzielić na kilka mniejszych, to możemy wówczas zastosować inne rozwiązanie. Można mianowicie co jakiś (krótki) czas pobierać oczekujące w kolejce komunikaty i zajmować się nimi, dzięki czemu interfejs będzie miał szansę zareagować na akcje użytkownika. Zazwyczaj oznacza to odpowiednio częste wywoływanie funkcji w rodzaju System.Windows.Forms.Application.DoEvents z .NET lub TApplication.ProcessMessages z VCL (Delphi). Jeśli na przykład dokonujemy jakichś obliczeń w pętli, wspomniane funkcje można wywoływać w każdym jej cyklu.
Jest nieco gorzej, jeśli piszemy z użyciem samego Windows API. Podobną funkcję musimy wtedy napisać sami. Nie jest to na szczęście trudne – należy po prostu “na chwilę” uruchomić naszą pętlę komunikatów, aby przetworzyła oczekujące zdarzenia:

  1. bool DoEvents()
  2. {
  3.     MSG msg;
  4.     while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  5.     {
  6.         if (msg.message == WM_QUIT) return false;
  7.         TranslateMessage (&msg);
  8.         DispatchMessage (&msg);
  9.     }
  10.     return true;
  11. }

Korzystamy z PeekMessage, która sprawdza, czy w kolejce nie ma już więcej zdarzeń i informuje nas o tym. Trzeba tylko pamiętać, że wśród tych zdarzeń może pojawić się WM_QUIT, który to komunikat oznacza konieczność zamknięcia aplikacji. Sposobem na jego obsłużenie może być chociażby wartość zwrócona z naszej funkcji; wywołujący będzie wówczas wiedział, że powinien zakończyć to, co aktualnie robi, gdyż program ma zostać zamknięty.
Oczywiście postać powyższej pętli powinna tak naprawdę być identyczna jak tej głównej, w funkcji WinMain – a więc niekoniecznie taka, jak powyżej. To się aczkolwiek zdarza wtedy, gdy korzystamy z okien dialogowych, akceleratorów menu i tym podobnych rzeczy. Samo to wymaga jednak na tyle dużej biegłości w Windows API, że odpowiednie przerobienie zaprezentowanej funkcji to przy tym naprawdę mały pikuś ;-)

Tags: ,
Author: Xion, posted under Programming » 2 comments

Odblokowywanie plików

2008-07-18 11:07

Czasami zdarza się, że chcemy usunąć plik, który okazuje się być używany przez inny proces lub system operacyjny. Często nie mamy pojęcia, dlaczego tak jest i kto ma jakiś interes w trzymaniu blokady na tym właśnie pliku. Zwłaszcza Vista, będąca paranoicznie przewrażliwiona na punkcie zachowania integralności systemu plików, jest bardzo restrykcyjna pod względem swobody kasowania zbiorów będących w użyciu.
Oczywiście w takiej sytuacji można zawsze zrestartować system, ale trudno uznać to za wygodne rozwiązanie :) Dobrze byłoby więc mieć sposób na dowiedzenie się, jaki proces używa danego pliku, aby ewentualnie go zakończyć lub w skrajnym przypadku po prostu ubić.

I tu jest problem, bowiem w Windows nie ma na to prostego sposobu. Dotyczy to między innymi istnienia jakiegoś API, które by na to pozwalało; w najlepszym przypadku należy posłużyć się narzędziami z DDK, czyli pakietu służącego do… pisania sterowników działających w trybie jądra (kernel mode). Podobnie rzecz ma się z istnieniem wbudowanych w system programów, służących do tego celu (a więc czegoś podobnego do uniksowej komendy lsof). Odpowiednie narzędzia są jedynie częścią pakietów dodatkowych, jak Windows Server 2003 Resource Kit (niekompatybilny z Vistą) czy Windows Sysinternals. Mogą być one jednak dość kłopotliwe w obsłudze.

Dlatego podzielę się moim niedawnym odkryciem, którym jest mały i niezwykle przydatny programik o nazwie Unlocker. Potrafi on dokładnie to, o czym jest tu mowa: wylistować procesy, które używają danego pliku. Działa on przy tym na każdej sensownej wersji Windows, integruje się z menu kontekstowym plików dla większej wygody, no i jest do tego aplikacją freeware.
Rzadko robię czemuś aż taką “reklamę”, ale w tym przypadku uznałem, że tak dobrym i użytecznym narzędziem należy się niezwłocznie podzielić ze światem :)

Tags: ,
Author: Xion, posted under Applications » 5 comments

Skróty i linki NTFS

2008-06-07 15:26

Tworzenie skrótu w Windows VistaSystem Windows od niepamiętnych czasów (a dokładniej od wersji 95) pozwala na tworzenie skrótów (shortcut), czyli plików będących odwołaniami do innych plików lub katalogów. Skróty mają zwykle rozszerzenie .lnk i występują głównie w katalogach tworzących strukturę Menu Start.
Wewnętrznie nie ma w nich nic pomysłowego, gdyż są to zwykłe pliki w formacie na wpółbinarnym, zawierające docelową ścieżkę lub URI (np. adres internetowy). Ich obsługa realizowana jest na poziomie Eksploratora Windows, więc nie są one specjalnie funkcjonalne. Otwarcie pliku skrótu w dowolnym programie nie spowoduje na przykład odczytania zawartości docelowego pliku, lecz samego skrótu (który zwykle ma kilkaset bajtów). Podobnie skrót do katalogu Foo o nazwie Bar.lnk nie spowoduje, że do pliku Foo/Coś.txt odwołamy się poprzez Bar.lnk/Coś.txt.

Ilustracja działania hardlinków
Ilustracja działania linków twardych
(Źródło: Wikipedia)

Taką funkcjonalność zapewniają jednak linki twarde i symboliczne, obecne w nowszym wersjach NTFS. Są one bardzo podobne do swoich odpowiedników w systemach plików ext2 i ext3 (uniksowych). I tak:

  • Link twardy (hardlink) to jakby alternatywna nazwa dla pliku, czyli nowa pozycja systemu plików odwołująca się do tych samych danych. Używając którejkolwiek z nich, można zmienić zawartość pliku i modyfikacje te będące widoczne dla innych, nawet jeśli uzyskają oni dostęp do pliku za pomocą innych jego nazw.
    W Windows 2000 i nowszych linki twarde można tworzyć poleceniem fsutil hardlink create link cel, a w Windows Vista dodatkowo mklink /H link cel. Programowo robi się funkcją WinAPI o nazwie CreateHardLink.
  • Link symboliczny (symlink) jest z kolei łączem do istniejącej nazwy pliku lub katalogu; zamiast do faktycznych danych na dysku odwołuje się więc do innego elementu systemu plików. To właściwie taki skrót pozbawiony ograniczeń, o których wspominałem na początku. Możliwe jest jednak, aby programy operowały bezpośrednio na linkach symbolicznych, o ile odpowiednio ładnie o to poproszą :)
    W miarę porządna implementacja obsługi symlinków jest niestety zawarta dopiero w Windows Vista; można je tworzyć programem mklink (trzeba jednak zaznaczać jawnie, czy robimy link do pliku czy do katalogu). We wcześniejszych wersjach możliwe jest jedynie tworzenie NTFS junctions, będących “linkami” tylko do katalogów oraz obarczonych innymi ograniczeniami (na przykład Eksplorator w Windows XP dość słabo sobie z nimi radzi).

Jak nietrudno zauważyć, podstawową zaletą linków nad zwykłymi skrótami jest to, że te pierwsze są obsługiwane na poziomie systemu plików. Wobec tego działają one w dowolnym programie i zupełnie przezroczyście dla aplikacji. Trochę szkoda, że ten przydatny drobiazg pochodzący z systemów uniksowych dopiero teraz pojawia się w Windows… ale przecież lepiej późno niż wcale ;]

Tags: ,
Author: Xion, posted under Programming » 3 comments
 


© 2017 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.