Escolar Documentos
Profissional Documentos
Cultura Documentos
w systemie Windows.
Wydanie IV
Autor: Johnson M. Hart
Tumaczenie: Tomasz Walczak
ISBN: 978-83-246-2780-6
Tytu oryginau: Windows System
Programming (4th Edition)
Format: 168x237, stron: 752
SPIS TRECI
Rysunki .................................................................................13
Tabele ...................................................................................15
Listingi ..................................................................................17
Przebiegi programw ...........................................................21
Wstp ....................................................................................23
O autorze ..............................................................................33
Rozdzia 1. Wprowadzenie do systemu Windows ...................................35
Podstawy systemw operacyjnych ......................................................................... 36
Ewolucja systemu Windows ...................................................................................... 37
Wersje systemu Windows .......................................................................................... 37
Pozycja systemu Windows na rynku ...................................................................... 40
System Windows, standardy i systemy o otwartym dostpie
do kodu rdowego ................................................................................................ 41
Podstawy systemu Windows .................................................................................... 43
Przenono 32- i 64-bitowego kodu rdowego ............................................ 46
Biblioteka standardowa jzyka C kiedy korzysta z niej
do przetwarzania plikw? ....................................................................................... 47
Co jest potrzebne do korzystania z tej ksiki? ................................................... 48
Przykad proste sekwencyjne kopiowanie pliku ........................................... 50
Podsumowanie .............................................................................................................. 58
wiczenia ......................................................................................................................... 61
SPIS
TRECI
SPIS
TRECI
SPIS
TRECI
SPIS
TRECI
10
SPIS
TRECI
SPIS
TRECI
11
Dodatek B
12
SPIS
Dodatek C
TRECI
Bibliografia .........................................................................705
Skorowidz ...........................................................................709
R O Z D Z I A
1 3
Ta terminologia bywa mylca, poniewa system Windows udostpnia wiele usug, ktre
nie s opisanymi tu usugami systemu Windows. Znaczenie powinno wynika z kontekstu
(podobnie zrozumienie pojcia system Windows przy omawianiu interfejsu API nie sprawiao problemu).
549
550
ROZDZIA 13.
USUGI
SYSTEMU
WINDOWS
W tym rozdziale pokazano te, jak przeksztaci istniejc aplikacj konsolow w usug systemu Windows, a take jak instalowa , obserwowa
i kontrolowa usugi. Znajduje si tu take omwienie rejestrowania zdarze
(mechanizm ten umoliwia usudze zapis wykonanych operacji w pliku).
FUNKCJA
MAIN()
551
Funkcja main()
Nowa funkcja main() wywoywana przez meneder SCM ma za zadanie
rejestrowa usug w menederze i uruchamia program rozdzielajcy do
sterowania usug. Wymaga to wywoania funkcji StartServiceCtrl
Dispatcher z nazwami i punktami wejcia usug logicznych.
BOOL StartServiceCtrlDispatcher (
SERVICE_TABLE_ENTRY *lpServiceStartTable)
Jedyny parametr, lpServiceStartTable, to adres tablicy z elementami SERVICE_TABLE_ENTRY. Kady taki element to nazwa i punkt wejcia usugi logicznej. Kocem tablicy jest para elementw NULL.
Funkcja zwraca warto TRUE, jeli rejestracja zakoczya si powodzeniem.
Gwny wtek procesu usugi wywoujcego funkcj StartService
CtrlDispatcher nawizuje poczenie z menederem SCM. Meneder
ten rejestruje usug (lub usugi), przy czym wtek wywoujcy suy jako
program rozdzielajcy do sterowania usug. Meneder SCM nie zwraca
sterowania do wtku wywoujcego do czasu zakoczenia pracy przez
wszystkie usugi. Warto zauway , e usugi logiczne nie rozpoczynaj
dziaania od razu. Uruchomienie usugi wymaga wywoania opisanej dalej
funkcji StartService.
Listing 13.1 przedstawia typowy program gwny usugi z jedn usug
logiczn.
Listing 13.1. Funkcja main gwny punkt wejcia usugi
#include "Everything.h"
void WINAPI ServiceMain (DWORD argc, LPTSTR argv[]);
static LPTSTR serviceName = _T("SocketCommandLineService");
/* Gwna procedura uruchamiajca program rozdzielajcy do sterowania usug. */
VOID _tmain (int argc, LPTSTR argv[])
{
SERVICE_TABLE_ENTRY dispatchTable[] =
{
{ serviceName, ServiceMain },
{ NULL, NULL }
};
552
ROZDZIA 13.
USUGI
SYSTEMU
WINDOWS
if (!StartServiceCtrlDispatcher (dispatchTable))
ReportError (_T("Nie mozna uruchomic programu
rozdzielajacego."), 1, TRUE);
/* Funkcja ServiceMain() zadziaa po uruchomieniu jej przez meneder SCM. */
/* Sterowanie jest zwracane do tego miejsca dopiero po zamkniciu wszystkich usug. */
return;
}
Funkcje ServiceMain()
Tablica przydziau okrela funkcje, jak pokazano to na listingu 13.1, a kada
z nich reprezentuje usug logiczn. Funkcje te to wzbogacone wersje
podstawowego programu przeksztaconego na usug, a meneder SCM
wywouje kad usug logiczn w osobnym wtku. Usuga logiczna moe
z kolei uruchomi dodatkowe wtki, takie jak wtki robocze serwera generowane przez programy serverSK i serverNP. Czsto usuga systemu Windows obejmuje tylko jedn usug logiczn. Na listingu 13.2 usuga logiczna
to zmodyfikowana wersja gwnego serwera (listing 12.2). W jednej usudze
systemu Windows mona uruchomi usugi logiczne oparte na gniazdach
i potokach nazwanych. Wtedy naley udostpni dwie funkcje gwne
usugi.
Cho funkcja ServiceMain() jest oparta na funkcji main() oraz ma
parametry z liczb i acuchem argumentw, warto zwrci uwag na jedn
ma rnic. Funkcj t naley zadeklarowa jako void WINAPI. Nie
powinna ona zwraca wartoci typu int, jak robi to zwyka funkcja main().
FUNKCJE SERVICEMAIN()
553
SERVICE_STATUS_HANDLE
RegisterServiceCtrlHandlerEx (
LPCTSTR lpServiceName,
LPHANDLER_FUNCTION_EX lpHandlerProc,
LPVOID lpContext)
Parametry
Parametr lpServiceName to podana przez uytkownika nazwa usugi
umieszczona we wpisie dotyczcym danej usugi logicznej w tablicy usug.
Nazwa ta powinna odpowiada nazwie funkcji ServiceMain zarejestrowanej za pomoc funkcji StartServiceCtrlDispatcher.
Parametr lpHandlerProc to adres rozbudowanej procedury obsugi
opisanej w dalszym podrozdziale.
Parametr lpContext to zdefiniowane przez uytkownika dane przekazane do procedury sterujcej. Umoliwiaj one jednej procedurze sterujcej rozrnianie wielu korzystajcych z niej usug.
Jeli wystpi bd, zwracana warto (obiekt typu SERVICE_STATUS_
HANDLE) to 0. Do zbadania bdw naley zastosowa standardowe
metody.
554
ROZDZIA 13.
USUGI
SYSTEMU
WINDOWS
BOOL SetServiceStatus (
SERVICE_STATUS_HANDLE hServiceStatus,
LPSERVICE_STATUS lpServiceStatus)
Parametry
Parametr hServiceStatus to warto typu SERVICE_STATUS_HANDLE
zwrcona przez funkcj RegisterServiceCtrlHandlerEx (dlatego
naley j wywoa przed funkcj SetServiceStatus).
Parametr lpServiceStatus wskazuje struktur SERVICE_STATUS.
Opisuje ona waciwoci, stan i moliwoci usugi.
Struktura SERVICE_STATUS
Oto definicja struktury SERVICE_STATUS:
typedef struct _SERVICE_STATUS {
DWORD dwServiceType;
DWORD dwCurrentState;
DWORD dwControlsAccepted;
DWORD dwWin32ExitCode;
DWORD dwServiceSpecificExitCode;
DWORD dwCheckPoint;
DWORD dwWaitHint;
} SERVICE_STATUS, *LPSERVICE_STATUS;
Parametry
Parametr dwWin32ExitCode to normalny kod wyjcia wtku usugi logicznej. Usuga musi ustawi ten kod na warto NO_ERROR w czasie dziaania i przy standardowym koczeniu pracy. Mimo nazwy parametru mona
go uywa take w aplikacjach 64-bitowych. Czon 32 pojawia si te
w innych nazwach.
Parametr dwServiceSpecificExitCode mona wykorzysta do zasygnalizowania bdu w czasie uruchamiania lub zatrzymywania usugi, jednak
warto ta zostanie zignorowana, jeli parametr dwWin32ExitCode ma
warto rn od ERROR_SERVICE_SPECIFIC_ERROR.
Usuga powinna okresowo zwiksza warto parametru dwCheckPoint,
aby informowa o przechodzeniu przez wszystkie etapy pracy, w tym ini-
FUNKCJE SERVICEMAIN()
555
Znaczenie
SERVICE_WIN32_OWN_PROCESS
SERVICE_WIN32_SHARE_PROCESS
SERVICE_KERNEL_DRIVER
SERVICE_FILE_SYSTEM_DRIVER
SERVICE_INTERACTIVE_PROCESS
556
ROZDZIA 13.
USUGI
SYSTEMU
WINDOWS
Znaczenie
SERVICE_STOPPED
SERVICE_START_PENDING
SERVICE_STOP_PENDING
SERVICE_RUNNING
Usuga dziaa.
SERVICE_CONTINUE_PENDING
SERVICE_PAUSE_PENDING
SERVICE_PAUSED
PROCEDURA
STERUJCA USUGI
557
Znaczenie
SERVICE_ACCEPT_STOP
SERVICE_ACCEPT_PAUSE_CONTINUE
SERVICE_ACCEPT_SHUTDOWN
(funkcja ControlService nie moe
SERVICE_ACCEPT_PARAMCHANGE
Parametr dwControl okrela wysany przez meneder SCM sygna sterujcy, ktry naley przetworzy .
Parametr ten przyjmuje 14 wartoci, w tym te wymienione w tabeli 13.3.
Oto pi wartoci istotnych w omawianym przykadzie:
SERVICE_CONTROL_STOP
SERVICE_CONTROL_PAUSE
SERVICE_CONTROL_CONTINUE
SERVICE_CONTROL_INTERROGATE
SERVICE_CONTROL_SHUTDOWN
558
ROZDZIA 13.
USUGI
SYSTEMU
WINDOWS
Mona te stosowa zdefiniowane przez uytkownika wartoci z przedziau od 128 do 255, jednak nie wykorzystano ich w tym miejscu.
Parametr dwEventType ma zwykle warto 0, jednak do zarzdzania
urzdzeniami su wartoci niezerowe (omawianie tego zagadnienia wykracza poza zakres ksiki). Parametr lpEventDate udostpnia dodatkowe dane wymagane dla niektrych zdarze.
Ostatni parametr, lpContext, zawiera zdefiniowane przez uytkownika dane przekazane do funkcji RegisterServiceCtrlHandlerEx przy
rejestrowaniu okrelonej procedury obsugi.
Procedura obsugi jest wywoywana przez meneder SCM w tym samym
wtku, co program gwny, i jest zwykle napisana jako instrukcja switch.
Ilustruj to przykady.
Rejestrowanie zdarze
Usugi dziaaj bezwejciowo bez interakcji z uytkownikiem, dlatego
zwykle nie powinny bezporednio wywietla komunikatw o stanie. W systemach starszych ni Vista i NT6 niektre usugi tworzyy konsol, pole
komunikatw lub okno do interakcji z uytkownikiem. Obecnie techniki
te nie s ju dostpne.
Rozwizanie tego problemu polega na rejestrowaniu zdarze w pliku
dziennika lub wykorzystaniu mechanizmu rejestrowania zdarze z systemu Windows. Takie zdarzenia s przechowywane w systemie Windows
i mona je wywietli za pomoc przegldarki zdarze dostpnej w Narzdziach administracyjnych w Panelu sterowania.
Dalszy przykadowy program SimpleService (listing 13.2) rejestruje wane
zdarzenia i bdy usugi w pliku dziennika. W wiczeniu poproszono o zmodyfikowanie tego programu przez zastosowanie zdarze systemu Windows.
PRZYKAD
NAKADKA NA USUGI
559
#include "Everything.h"
#include <time.h>
#define UPDATE_TIME 1000 /* Sekunda odstpu midzy aktualizacjami. */
VOID LogEvent (LPCTSTR, WORD), LogClose();
BOOL LogInit(LPTSTR);
void WINAPI ServiceMain (DWORD argc, LPTSTR argv[]);
VOID WINAPI ServerCtrlHandler(DWORD);
void UpdateStatus (int, int);
int ServiceSpecific (int, LPTSTR *);
static BOOL shutDown = FALSE, pauseFlag = FALSE;
static SERVICE_STATUS hServStatus;
static SERVICE_STATUS_HANDLE hSStat; /* Uchwyt do ustawiania stanu. */
static LPTSTR serviceName = _T("SimpleService");
static LPTSTR logFileName = _T(".\\LogFiles\\SimpleServiceLog.txt");
static BOOL consoleApp = FALSE, isService;
/* Gwna procedura uruchamiajca program rozdzielajcy do sterowania usug. */
/* Program mona te uruchomi jako niezalen aplikacj konsolow. */
/* Stosowanie: simpleService [-c] */
/*
Opcja -c powoduje uruchomienie aplikacji konsolowej zamiast usugi. */
VOID _tmain (int argc, LPTSTR argv[])
{
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ serviceName, ServiceMain},
{ NULL,
NULL }
};
Options (argc, argv, _T("c"), &consoleApp, NULL);
isService = !consoleApp;
/* Inicjowanie pliku dziennika. */
if (!LogInit (logFileName)) return;
if (isService) {
LogEvent(_T("Uruchamianie programu rozdzielajacego."),
EVENTLOG_SUCCESS);
StartServiceCtrlDispatcher (DispatchTable);
560
ROZDZIA 13.
USUGI
SYSTEMU
WINDOWS
} else {
LogEvent(_T("Uruchamianie aplikacji."), EVENTLOG_SUCCESS);
ServiceSpecific (argc, argv);
}
LogClose();
return;
}
/* Punkt wejcia w postaci funkcji ServiceMain wywoywanej przez program gwny. */
void WINAPI ServiceMain (DWORD argc, LPTSTR argv[])
{
LogEvent (_T("Wchodzenie do funkcji ServiceMain."),
EVENTLOG_SUCCESS);
hServStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
hServStatus.dwCurrentState = SERVICE_START_PENDING;
hServStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
hServStatus.dwWin32ExitCode = NO_ERROR;
hServStatus.dwServiceSpecificExitCode = 0;
hServStatus.dwCheckPoint = 0;
hServStatus.dwWaitHint = 2 * UPDATE_TIME;
hSStat =
RegisterServiceCtrlHandler( serviceName, ServerCtrlHandler);
if (hSStat == 0) {
LogEvent (_T("Nie mozna zarejestrowac procedury obslugi."),
EVENTLOG_ERROR_TYPE);
hServStatus.dwCurrentState = SERVICE_STOPPED;
hServStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
hServStatus.dwServiceSpecificExitCode = 1;
UpdateStatus (SERVICE_STOPPED, -1);
return;
}
LogEvent (_T("Zarejestrowano procedure sterujaca."),
EVENTLOG_SUCCESS);
SetServiceStatus (hSStat, &hServStatus);
LogEvent (_T("Stan SERVICE_START_PENDING."), EVENTLOG_SUCCESS);
/* Uruchamianie zada specyficznych dla usugi. Oglne operacje zostay wykonane. */
ServiceSpecific (argc, argv);
/* Sterowanie jest zwracane do tego miejsca dopiero po zakoczeniu
dziaania funkcji ServiceSpecific, co oznacza zamknicie systemu. */
LogEvent (_T("Watki uslugi zakonczyly prace."),
EVENTLOG_SUCCESS);
LogEvent (_T("Ustawianie stanu na SERVICE_STOPPED."),
EVENTLOG_SUCCESS);
PRZYKAD
NAKADKA NA USUGI
561
562
ROZDZIA 13.
USUGI
SYSTEMU
WINDOWS
case SERVICE_CONTROL_INTERROGATE:
break;
default:
if (dwControl > 127 && dwControl < 256) /* Zdefiniowane przez
uytkownika. */
break;
}
UpdateStatus (-1, -1);
return;
}
void UpdateStatus (int NewStatus, int Check)
/* Ustawianie stanu usugi i punktu kontrolnego (na okrelon warto lub przez zwikszenie). */
{
if (Check < 0 ) hServStatus.dwCheckPoint++;
else hServStatus.dwCheckPoint = Check;
if (NewStatus >= 0) hServStatus.dwCurrentState = NewStatus;
if (isService) {
if (!SetServiceStatus (hSStat, &hServStatus)) {
LogEvent (_T("Nie mozna ustawic stanu."),
EVENTLOG_ERROR_TYPE);
hServStatus.dwCurrentState = SERVICE_STOPPED;
hServStatus.dwWin32ExitCode =
ERROR_SERVICE_SPECIFIC_ERROR;
hServStatus.dwServiceSpecificExitCode = 2;
UpdateStatus (SERVICE_STOPPED, -1);
return;
} else {
LogEvent (_T("Zaktualizowano stan uslugi."),
EVENTLOG_SUCCESS);
}
} else {
LogEvent (_T("Zaktualizowano stan niezaleznego programu."),
EVENTLOG_SUCCESS);
}
return;
}
/* Proste rejestrowanie zdarze w pliku. */
static FILE * logFp = NULL;
/* Bardzo prosta usuga rejestrujca (korzysta z pliku). */
VOID LogEvent (LPCTSTR UserMessage, WORD type)
{
TCHAR cTimeString[30] = _T("");
time_t currentTime = time(NULL);
_tcsncat (cTimeString, _tctime(¤tTime), 30);
/* Usuwanie znaku nowego wiersza na kocu acucha z czasem. */
cTimeString[_tcslen(cTimeString)-2] = _T('\0');
_ftprintf(logFp, _T("%s. "), cTimeString);
PRZYKAD
NAKADKA NA USUGI
563
"));
"));
"));
"));
}
BOOL LogInit(LPTSTR name)
{
logFp = _tfopen (name, _T("a+"));
if (logFp != NULL) LogEvent (_T("Zainicjowano rejestrowanie."),
EVENTLOG_SUCCESS);
return (logFp != NULL);
}
VOID LogClose()
{
LogEvent (_T("Zamykanie dziennika."), EVENTLOG_SUCCESS);
return;
}
Opcja c podawana w wierszu polece okrela, e kod naley uruchomi jako niezaleny program (na przykad w celach diagnostycznych).
Pominicie tej opcji powoduje wywoanie funkcji StartServiceCtrl
Dispatcher.
Innym dodatkiem jest plik dziennika. Dla uproszczenia jego nazw
zapisano na stae w kodzie. Usuga rejestruje w tym pliku istotne zdarzenia.
Na kocu znajduj si proste funkcje do inicjowania i zamykania dziennika
oraz rejestrowania komunikatw.
W komentarzach opisano kilka innych uproszcze i ogranicze.
564
ROZDZIA 13.
USUGI
SYSTEMU
WINDOWS
ZARZDZANIE
USUGAMI SYSTEMU
WINDOWS
565
Parametry
Jeli meneder SCM dziaa na komputerze lokalnym, parametr lpMachine
Name ma warto NULL, natomiast mona te uzyska dostp do menedera uruchomionego na maszynach z danej sieci.
Parametr lpDatabaseName ma zwykle warto NULL.
Parametr dwDesiredAccess ma standardowo warto SC_MANAGER_
ALL_ACCESS, jednak mona okreli bardziej ograniczone uprawnienia
dostpu, jak opisano to w dokumentacji dostpnej w internecie.
566
ROZDZIA 13.
USUGI
SYSTEMU
WINDOWS
SC_HANDLE CreateService (
SC_HANDLE hSCManager,
LPCTSTR lpServiceName,
LPCTSTR lpDisplayName,
DWORD dwDesiredAccess,
DWORD dwServiceType,
DWORD dwStartType,
DWORD dwErrorControl,
LPCTSTR lpBinaryPathName,
LPCTSTR lpLoadOrderGroup,
LPDWORD lpdwTagId,
LPCTSTR lpDependencies,
LPCTSTR lpServiceStartName,
LPCTSTR lpPassword);
Nie naley jednak prbowa pomija funkcji CreateService przez bezporednie manipulowanie rejestrem. O tym kluczu wspomniano tylko po to,
aby pokaza , w jaki sposb Windows przechowuje informacje o usugach.
Parametry
Parametr hSCManager to uchwyt typu SC_HANDLE zwrcony przez funkcj
OpenSCManager.
Parametr lpServiceName to nazwa uywana do pniejszego wskazywania usugi. Jest to jedna z nazw usug logicznych podanych w tablicy
przydziau w wywoaniu funkcji StartServiceCtrlDispatcher. Warto
zauway , e funkcj CreateService trzeba wywoa dla kadej usugi
logicznej.
Parametr lpDisplayName to nazwa usugi wywietlana uytkownikowi
w narzdziu administracyjnym Usugi (Panel sterowania/Narzdzia administracyjne) i w innych miejscach. Nazwa ta pojawia si natychmiast po udanym wywoaniu funkcji CreateService.
Do parametru dwDesiredAccess mona przypisa warto SERVICE_
ALL_ACCESS lub kombinacj wartoci GENERIC_READ, GENERIC_WRITE
i GENERIC_EXECUTE. Wicej szczegw na ten temat mona znale
w dokumentacji MSDN.
Wartoci parametru dwServiceType przedstawiono w tabeli 13.1.
ZARZDZANIE
USUGAMI SYSTEMU
WINDOWS
567
Parametr dwStartType okrela sposb uruchamiania usugi. W przykadach uyto ustawienia SERVICE_DEMAND_START, natomiast inne wartoci (SERVICE_BOOT_START i SERVICE_SYSTEM_START) umoliwiaj
uruchamianie usug sterownikw urzdze w czasie adowania lub uruchamiania systemu. Ustawienie SERVICE_AUTO_START informuje, e usug
naley wczy w czasie uruchamiania komputera.
Parametr lpBinaryPathName okrela pen ciek do pliku wykonywalnego. Koniecznie trzeba poda rozszerzenie .exe. Jeli cieka obejmuje odstpy, naley uy cudzysoww.
Inne parametry dotycz nazwy konta i hasa, grup sucych do czenia
usug, a take zalenoci, jeli istnieje kilka zalenych od siebie usug.
Wartoci parametrw konfiguracyjnych istniejcej usugi mona zmieni za pomoc funkcji ChangeServiceConfig i ChangeService
Config2. Ta druga jest prostsza i prawdopodobnie z tego powodu nie
nosi nazwy ChangeServiceConfigEx. Do wskazywania usug su
ich uchwyty, a wspomniane funkcje pozwalaj ustawi nowe wartoci
wikszoci parametrw. Mona na przykad poda now warto parametrw dwServiceType lub dwStartType, jednak nie mona zmieni
parametru dwAccess.
Istnieje te funkcja OpenService. Suy ona do pobierania uchwytu
nazwanej usugi. Aby wyrejestrowa usug z menedera SCM, naley uy
funkcji DeleteService, a do zamykania uchwytw SC_HANDLE przeznaczona jest funkcja CloseServiceHandle.
Uruchamianie usugi
Usuga po utworzeniu nie jest uruchomiona. Naley wywoa funkcj Ser
viceMain() przez podanie uchwytu uzyskanego za pomoc funkcji
CreateService. Razem z uchwytem naley poda parametry wiersza
polece (argc, argv) oczekiwane przez funkcj gwn usugi (czyli funkcj okrelon w tablicy przydziau).
BOOL StartService (
SC_HANDLE hService,
DWORD argc,
LPTSTR argv[])
568
ROZDZIA 13.
USUGI
SYSTEMU
WINDOWS
Kontrolowanie usugi
Usug mona kontrolowa przez nakazanie menederowi SCM wywoania
procedury sterujcej usugi z okrelonym kodem sterowania.
BOOL ControlService (
SC_HANDLE hService,
DWORD dwControlCode,
LPSERVICE_STATUS lpServStat)
PODSUMOWANIE
569
570
ROZDZIA 13.
USUGI
SYSTEMU
WINDOWS
#include "Everything.h"
static
static
static
static
int
int
int
int
PRZYKAD
571
SC_HANDLE hSc;
TCHAR executable[MAX_PATH+1],
quotedExecutable[MAX_PATH+3] = _T("\"");
/* Potrzebna jest pena cieka i jeli wystpuj odstpy cudzysowy. */
GetFullPathName (argv[3], MAX_PATH+1, executable, NULL);
_tcscat(quotedExecutable, executable);
_tcscat(quotedExecutable, _T("\""));
572
ROZDZIA 13.
USUGI
SYSTEMU
WINDOWS
return 0;
}
/* Usuwanie usugi
argv[1]: nazwa usuwanej usugi */
int Delete (int argc, LPTSTR argv[], LPTSTR command)
{
SC_HANDLE hSc;
PRZYKAD
573
stop
pause
resume
interrogate
user - zdefiniowane przez uytkownika
*/
static LPCTSTR commandList[] =
{ _T("stop"), _T("pause"), _T("resume"),
_T("interrogate"), _T("user") };
static DWORD controlsAccepted[] = {
SERVICE_CONTROL_STOP, SERVICE_CONTROL_PAUSE,
SERVICE_CONTROL_CONTINUE, SERVICE_CONTROL_INTERROGATE, 128 };
int Control (int argc, LPTSTR argv[], LPTSTR command)
{
SC_HANDLE hSc;
SERVICE_STATUS sStatus;
DWORD dwControl, i;
BOOL found = FALSE;
if (debug) _tprintf (_T("\nSterowanie usluga: %s"), argv[1]);
for (i= 0;
i < sizeof(controlsAccepted)/sizeof(DWORD) && !found; i++)
found = (_tcscmp (commandList[i], argv[2]) == 0);
if (!found) {
_tprintf (_T("\nNiedozwolone polecenie %s"), argv[1]);
return 1;
}
dwControl = controlsAccepted[i-1];
if (dwControl == 128) dwControl = _ttoi (argv[3]);
if (debug) _tprintf (_T("\ndwControl = %d"), dwControl);
hSc = OpenService(hScm, argv[1],
SERVICE_INTERROGATE | SERVICE_PAUSE_CONTINUE |
SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL |
SERVICE_QUERY_STATUS );
ControlService (hSc, dwControl, &sStatus);
if (dwControl == SERVICE_CONTROL_INTERROGATE) {
QueryServiceStatus (hSc, &sStatus);
_tprintf (_T("\nStan z funkcji QueryServiceStatus."));
_tprintf (_T("\nStan uslugi:"));
_tprintf (_T("\ndwServiceType: %d"), sStatus.dwServiceType);
_tprintf (_T("\ndwCurrentState: %d"),
sStatus.dwCurrentState);
_tprintf (_T("\ndwControlsAccepted: %d"),
sStatus.dwControlsAccepted);
574
ROZDZIA 13.
USUGI
SYSTEMU
WINDOWS
UWAGI
575
576
ROZDZIA 13.
USUGI
SYSTEMU
WINDOWS
dziennika zdarze. Nawet informacje o stanie mog pomc w okreleniu sprawnoci serwera i wykryciu symptomw usterek.
Jeli konieczne s skomplikowane prace konserwacyjne, mona zdiagnozowa program jako zwyk aplikacj za pomoc opcji c.
Podsumowanie
Usugi systemu Windows udostpniaj standardowe moliwoci w zakresie
dodawania utworzonych przez uytkownika usug do komputerw z system
Windows. Gotowy niezaleny program mona przeksztaci na usug za
pomoc metod opisanych w tym rozdziale.
Usugi mona tworzy , sterowa nimi i obserwowa ich dziaanie za
pomoc narzdzi administracyjnych lub programu ServiceShell zaprezentowanego w tym rozdziale. Meneder SCM kontroluje zainstalowane usugi
i ledzi ich dziaanie. W rejestrze znajduj si wpisy powizane z wszystkimi usugami.
Co dalej?
W rozdziale 14. opisano asynchroniczne operacje wejcia-wyjcia. Obejmuj
one dwie techniki do wykonywania wielu operacji odczytu i zapisu rwnolegle z przetwarzaniem danych. Nie trzeba przy tym korzysta z wtkw potrzebny jest tylko jeden wtek uytkownika.
W wikszoci przypadkw atwiej jest pisa programy za pomoc wielu
wtkw ni asynchronicznych operacji wejcia-wyjcia, a wydajno rozwiza opartych na wtkach jest zwykle wysza. Jednak asynchroniczne
operacje wejcia-wyjcia s niezbdne przy stosowaniu portw koczenia
operacji wejcia-wyjcia. Porty te s niezwykle przydatne przy budowaniu
skalowalnych serwerw, ktre mog obsugiwa du liczb klientw.
W rozdziale 14. omwiono te zegary oczekujce.
Lektura dodatkowa
W ksice Professional NT Services Kevin Miller dokadnie opisa usugi.
W niniejszym rozdziale nie omwiono sterownikw urzdze i ich interakcji z usugami. Informacje na te tematy mona znale na przykad
w ksice Programming the Microsoft Windows Driver Model, Second Edition Waltera Oneya.
WICZENIA
577
wiczenia
13.1. Zmodyfikuj program SimpleService (listing 13.2) przez zastosowanie
zdarze systemu Windows zamiast pliku dziennika. Potrzebne bd
funkcje RegisterEventSource, ReportEvent i Deregister
EventSource (kad z nich opisano w dokumentacji MSDN).
Rozwa ponadto wykorzystanie rejestrowania zdarze w systemie
Vista. Inna moliwo to zastosowanie systemu rejestrowania o otwartym dostpie do kodu rdowego, takiego jak Nlog (http://nlogproject.org/home).
13.2. Rozbuduj program serviceSK, tak aby w sensowny sposb przyjmowa polecenie wstrzymania. Oto sugestia wstrzymana usuga powinna zachowywa istniejce poczenia, ale nie moe przyjmowa
nowych pocze. Ponadto usuga powinna zakoczy przetwarzanie
odebranych da i wysa odpowiedzi, jednak nie mona akceptowa w niej dalszych da od klientw.
13.3. Program ServiceShell przy sprawdzaniu stanu usugi po prostu wywietla liczby. Rozwi ten program w taki sposb, aby przedstawia
stan w bardziej czytelnej postaci.
13.4. Przekszta program serverNP (listing 12.3) na usug.
13.5. Przetestuj program serviceSK z pliku Przykady. Zmodyfikuj go, tak
aby korzysta z rejestrowania zdarze.