Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
12
Добавлен:
20.04.2024
Размер:
19.21 Mб
Скачать

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

E

 

 

 

 

X

 

 

 

 

 

-

 

 

 

 

d

 

 

F

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

NOW!

o

>> codingto BUY

 

 

 

 

 

 

 

w Click

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

o

 

 

.

 

 

 

 

.c

 

 

 

p

 

 

 

g

 

 

 

 

 

df

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

 

 

 

 

Русскоязычное сообщество ISA Server

 

 

 

 

 

 

 

 

ISA Server SDK на страницах MSDN

 

 

 

 

UserMode.Ядросервераотвечаетзавзаимодействиессетевымиин-

 

Фильтруй базар

 

 

 

 

 

терфейсамикомпьютераивыполняеттранспортныефункции,работаяс

В момент старта Исы ее основная служба пробегает по списку за-

 

низкоуровневымисетевымипротоколами.Фильтрациясетевоготрафика

регистрированных фильтров и для каждого из них вызывает метод

 

осуществляетсянапользовательскомуровне—всепакетыпроходят

IFWXFilter::FilterInit. Он является точкой входа в фильтр, и

 

черезцепочкуфильтров.Каждыйфильтр—этоотдельнаяDLL’ка,выпол-

метод инициализирует доступные из файрвола глобальные перемен-

 

няющаяфункцииCOM-сервера.Фильтрыбывают,всвоюочередь,двух

ные фильтра. Их основное назначение — зарезервировать за фильтром

 

типов—анализирующиесетевойтрафикиреагирующиенаопределен-

определенные сетевые события, при возникновении которых ядро

 

ныесобытия.Таккакневозможнообъятьнеобъятное,остановимсяна

сервера будет передавать фильтру управление.

 

фильтрахдляИсыпервоготипа.Ужереализованныефильтры,которые

 

 

 

 

входятвсоставфайрвола,соответствуютпрактическивсемсетевым

 

// Инициализация сетевого фильтра

 

протоколамприкладногоуровня(FTP,SMTP,DNS,POP3,RPCит.д.).Ты

 

STDMETHODIMP CDMFilter::FilterInit

 

можешьпереопределитьих,заменивсобственнойреализацией,напри-

 

(IFWXFirewall * pIFWXFirewall,

 

мер,открытьзеленыйкоридорспам-трафику.Кэтойжегруппеотносятся

 

FwxFilterHookEvents * pFilterHookEvents)

 

фильтрыприложений(пригодятся,еслинужнообломатьдоступвСеть

{

 

 

определеннымпрогам)ифильтрысетевыхпортов(обламываютторрент-

 

// Сообщаем файрволу, какое именно событие

 

сосунов).

 

будем отслеживать

 

Атеперь—мат.часть.Расслабься,еебудетсовсемнемного.Нашацель

 

*pFilterHookEvents = m_FwxFilterHookEvents;

 

—вкурить,какимобразомвИсеработаютфильтры.Любойфильтрестьне

 

 

 

 

чтоиное,какносительсетевыхправил.Правила,всвоюочередь,бывают

 

return S_OK;

 

двухтипов—правиладоступаиправилапубликациисервисов.Другими

}

 

 

словами,фильтрующиевходящийтрафикиисходящий.

 

 

 

 

 

 

 

 

Одинсетевойфильтрможетобъединятьвсебенесколькоправилфильтра-

Послетого,какфильтрпроинициализирован,заработупринимается

 

циитрафика,относящихсякразнымгруппам.

обработчиксобытийIFWXFilter::AttachToSession —сообщаето

 

Идемдальше.Всефильтрымогутотрабатыватьразличныесценарии

каждойновойсессии,установленнойклиентамисИсой.Длясессиисоеди-

 

проверкисетевыхпакетов,основанныенаотслеживаниииспользуемых

ненияклиентассерверомфильтрсоздаетобъект,реализующийинтерфейс

 

протоколов,NAT-сеансовифильтрацииконтента.

IFWXSessionFilter,ипередаетфайрволуссылкунанего.

 

ВсеISA-фильтрывыстраиваютсявцепочку.Врезультате,проходящаячерез

 

 

 

 

файрволинформациябудетобработанакаждымфильтромизцепочки.

 

// Подключаемся к сессии

 

Организоватьизбирательнуюобработкупакетовкакими-либоотдельными

 

STDMETHODIMP CDMFilter::AttachToSession

 

фильтраминеполучится.Затоестьвозможностьвыстроитьнесколькотаких

 

(IFWXSession *piSession,

 

цепочексуникальнымнаборомфильтров,ивразличныхсценарияхпропус-

 

IFWXSessionFilter **

 

катьтрафикчерезцепочку,определеннуюлогикойсетевойзащиты.

 

piSessionFilter, PFwxFilterHookEvents,

 

 

 

 

 

pFilterHookEvents)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Точкивхода

Любойразрабатываемыйтобойвеб-фильтрдляISAServerдолжен иметь,какминимум,однуточкувхода.Вкачестветаковойвсегда выступаетпараопределенныхфункций.ДляISAServer2004это— функцииGetWPXFilterVersion() и HttpWPXFilterProc().

Для2006 оймогутбытьиспользованыкакуказанныевыше функции(сделанодлятого,чтобысохранитьсовместимостьс фильтрами,написаннымидляпредыдущейверсиифайрвола),так иоптимизированныеподвозможностиISAServer2006функции

GetFilterVersion() и HttpFilterProc().

Веб-фильтры

Веб-фильтрыпредставляютсобойособуюразновидностьрасши- ренийISAServer.Реагируянаразличныесобытия,возникающие вмодулеWebproxy,веб-фильтрымогутанализироватьHTTP-за- головки,принимаянаосноветакогоанализаодноизвозможных решений.

Всевеб-фильтрыреализованыввидединамическихбиблиотек, инициализируемыхвмоментстартаслужбыMicrosoftFirewallи остающихсявпамятидозавершенияработыслужбы.

xàêåð 09 /117/ 08

109

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

w Click

to BUY

 

>> coding

 

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

links

Залежи документа-

ции по ISA Server на MSDN: msdn.microsoft. com/en-us/library/ aa155227.aspx

Русскоязычное со-

общество ISA Server

www.isaserver.ru

Здесь можно скачать свежую версию как самого файрвола, так и SDK к нему: go.microsoft.com/ fwlink?linkid=41251

Кое-что о файрволах можно найти и в народной энциклопе-

дии — www.wikipedia. org/firewall

info

Помни, что не ты один такой умный и регулярно проводи аудит своего файрвола на предмет незнакомых и неизвестно откуда появившихся фильтров и расширений.

Файрвол— жертваDoS-атак

Присозданиисвоегорасширениядляфайрвола(не важно,ISAServerилилюбогодругого,поддерживающегонаписаниерасширенийстороннимиразработчиками),важнопомнитьотом,чтосистемнаяпамять нерезиноваяиустанавливатьограничения,какпо размеруобрабатываемыхсетевыхпакетов,такипо времени,отведенномунаобслуживаниеоднойсессии. Иначеможнопопастьвоченьнеприятнуюситуацию, когдафайрвол,несумевпереваритьслишкомбольшую порциюданных,станетпричинойкрахавсейсистемы.

{

HRESULT hr = S_OK;

//Создаем объект, связанный с сессией

CComObject<CDMSessionFilter>

*pSessionFilter;

hr = CComObject<CDMSessionFilter>:: CreateInstance(&pSessionFilter);

if (FAILED(hr))

{

return hr;

}

pSessionFilter->AddRef();

// Получаем ссылки на созданные объекты

*pFilterHookEvents = m_FwxFilterHookEvents;

*piSessionFilter = pSessionFilter;

return S_OK;

}

Черезэтотобъектвдальнейшемфайрволибудетобщатьсяс фильтром,посылаясигналытолькоотехсобытиях,которые егоинтересуют.Получивсигналотом,чтовСетипроисходитнечтоинтересное,фильтрсоздаетэкземпляркласса IFWXDataFilterиассоциируетегостекущимсоединени-

емчерезвызовIFWXConnection::AttachDataFilter.

В качестве финального аккорда создадим два сокета

(IFWXDataFilter::SetSockets) и прокачаем данные из точки А в точку B, как учила меня сексапильная математичка в седьмом классе (упс, Анна Сергеевна, надеюсь вы не читаете журнал «][акер»). Но об этом ниже.

Из точки А в точку В

ВлюбомISA-фильтреиспользуетсяасинхронныйввод/ вывод.ФильтруправляетзапросамиSEND/RECVчерез обращениякобъектуIFWXSocket,которыйразмещаетсяв адресномпространствеядрафайрволаивозвращаетсодер- жимоеI/O-буферовчерезинтерфейсIFWXIOCompletion. Получается,процесспередачисетевыхпакетовчерез фильтрпрост,какдвабайтаобасфальт.Беремуказательна IFWXSocketиотправляемемуRECV-запрос.Вответполуча-

емсодержимоебуфера.Шаманимнаднимнемного,например, проанализировавнапредметналичиязапрещенноготипа данных,отправляемобъекту IFWXSocketзапросSENDив

Архитектура ISA Server

вдогонку—содержимоеI/Oбуфера.Одальнейшемпозаботит- сяфайрвол,точнее,егоядро.

Естественно,чтобыпростополучитьданныеипередатьихдальшепоСети,многоуманенадо.Даикакойтогдасмыслгородить весьэтотогород? Воттут-то(междуполучениемпакетовиих отправкой)икроетсяДаолюбогоISA-фильтра.Именновэтом местеканалапередачиданныхчерезISAServerможнотворитьс сетевымипакетамивсе,чтоугодно.Чтовитогеполучитклиентна свойзапрос,—целикомиполностьювтвоейвласти.

Нестанумаратьпопустубумагуописаниемсферическогоконя ввакууме,—воттебеконкретныйпример.Предположим, нашфильтрдолженпередаватьпакеты—безкаких-либо изменений,ноприэтомподробножурналировать:кто,что, кому,изачем.Первымделомполучаемссылкинасокеты отправителяиполучателяспомощьюпростыхконструкций типаm_spInternalSocket = piInternalSocketи m_spExternalSocket = piExternalSocket.Теперь можносоздаватьасинхронныйканалпередачиданных. Делаетсяэтоспомощьюметода,возвращающеговкачестве результатасвоейработыобъектклассаSTDMETHODIM: CDMDataFilter::CompleteAsyncIO().Послечего можнопрочитатьвходнойбуфер:

BYTE* pBuffer = NULL; DWORD dwBuffSize = 0;

hr = pIOBuffer->GetBufferAndSize (&pBuffer,&dwBuffSize);

Отправкаполученныхданных—ничутьнесложнее.Обраща- емсяксозданномуранеесокетуисливаемвнегосодержимое I/O-буфера.

HRESULT hr; CComPtr<IFWXSocket> spSocket; GetInternalSocket(&spSocket); if (spSocket)

{

hr = spSocket->Send(pBuffer,NULL, ocWriteToInternal);

if (FAILED(hr)) return hr;

}

return S_OK;

Перед этим мы можем сделать вызов любой другой функции, обрабатывающей содержимое буфера. Например, hack(pBuffer). Реализация самой функции и определяет поведение фильтра. В частности, если ты хочешь вести подробный лог о передаваемых пакетах,

можешь воспользоваться представленным в SDK методом

DumpBuffer().

110

xàêåð 09 /117/ 08

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

E

 

 

 

 

X

 

 

 

 

 

-

 

 

 

 

d

 

 

F

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

NOW!

o

>> codingto BUY

 

 

 

 

 

 

 

w Click

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

o

 

 

.

 

 

 

 

.c

 

 

 

p

 

 

 

g

 

 

 

 

 

df

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

ISA Server SDK

Зарегистрирую. Недорого.

ОК,свойфильтрдляИсымынаписали.Акакеготеперьфайрволупод-

 

 

 

сунуть?Естьдвапути—написатьпростенькийскрипт,осуществляющий

 

ISA Server

 

регистрациюфильтра,илипредусмотретьмеханизмрегистрациинепос-

 

 

 

редственновсамомфильтре.Вовторомслучаерегистрацияпроисходит

Нашазадачасводитсяктому,чтобыпоместитьзаписьоновомфильтре

спомощьюэкспортафункцииDllInstall,вызываемойвмоментобращевконфигурационныймассивИсы.Кактыужезнаешь,сточкизрения

ниякregsrv32 спараметром /I.

внутреннейорганизациифайрвола,этобудетвыглядетькакдобавление

Строгоговоря,чтобызарегистрироватьсвойфильтрвИсе,необходимо

нового FPCWebFilter объектавколлекцию FPCWebFilters.Следо-

одновременноевыполнениеследующихусловий.Во-первых,DLLтвоего

вательно,нужнокак-тодобратьсядоэтойсамойколлекции.Порывшисьв

фильтрадолжнанаходитьсянатомжекомпьютере,чтоиISAServer.Во-

документации,явыяснил,какэтоможнореализовать.Следизацепочкой.

вторых,фильтрдолженбытьзарегистрированкакобъектконфигурации

Конфигурационныймассивсерверадоступендляизмененияизвне.В

компьютера.И,в-третьих,ондолженбытьзарегистрированкакУЖЕуста-

массивесодержитсяссылканаобъекткласса FPCExtensions.Уэтого

новленныйнакомпьютер.

объектаестьнесколькопубличныхполей.Одноизтакихполейимеет

Независимооттого,какойспособрегистрациитыбудешьиспользовать,

название WebFilters,и,какнетруднодогадаться,представляетсобой

техническионаосновананаиспользованиичетырехэкспортируемыхCOM-

ссылкунаколлекциюFPCWebFilters.Науровнеоперационнойсистемы

интерфейсов:

этаколлекцияпредставленакакобычнаяветкареестра.Означаетэто,что,

 

 

 

 

 

 

 

 

•IFWXFilterAdmin

—регистрацияфильтра;

добавивбуквальнотристрокивкоднашегорасширениядляISAServer,мы

 

 

 

 

 

 

 

•FPCEventDefintions

—регистрациясобытий,отслеживаемыхфильтром;

сможемвручнуюегозарегистрировать(тривиальнымспособомспомощью

 

 

 

 

 

 

•FPCAlerts

—регистрациясообщений,генерируемыхфильтром;

regsrv32).Дляэтогодобавляемкнашемуфильтрунебольшуюфункцию

 

 

 

 

 

 

•FPCApplicationFilter

—инициализациязначениямипоумолчанию.

следующеговида:

Чтобысообщитьядруфайрвола,закакимипротоколамибудетна-

 

блюдатьсвежеиспеченныйфильтр,используетсямассив:GUID

STDAPI DllRegisterServer(void){

ProtocolsToFilter[] = {SMTP_PROTOCOL_GUID_BIN, SMTP_

HRESULT hr = RegisterWebFilter(true);

SERVER_PROTOCOL_GUID_BIN}.Дляописанияфильтраиспользуется

return FAILED(hr) ? S_FALSE : S_OK;

структурасоследующимиполями:

}

 

 

 

 

 

 

•CLSID_DMFilter

—GUID;

 

 

 

 

 

 

•bstrFilterName

—наименование;

ТеперьтыможешьподключитьсвойфильтркработающейнаполномходуИсе

 

 

 

 

•bstrFilterDescription

—описание;

безкаких-либовопросовсеестороны.Адальше—ужеделотвоейфантазии.

 

 

 

•bstrFilterVendor

—разработчик;

 

 

Лирическо-спортивное

•bstrFilterVersion

—версия.

Развеемвсевозможныевопросы.Воттебеописаниетого,какрегистрация

Обычнонаэтомместеавторыповсемправиламжанраподводятитог

фильтраилилюбогодругогорасширениядляISAServerвыглядитнапрак-

своемуповествованию,резюмируянаиболееважныемоменты,делая

тике.ПервымделомсоздаетсяэкземплярCOM-объекта FPCWebFilter,

умныеипространныевыводы.Сегоднямнехотелосьбынемногоотойтиот

входящийвколлекцию FPCWebFilters.Дляидентификациикаждогоиз

традиций.Статья,которуютытолькочтопрочитал,писаласьзанесколько

такихобъектоввколлекциииспользуетсяглобальныйуникальныйиден-

днейдоначалаПекинскойолимпиады.Хочетсяверить,чтороссийская

тификатор(GUID).Коллекцияобъектов FPCWebFilters предоставляет

команданадеретвсемпятуюточкуизавоюетнаибольшееколичество

отдельныеметодыдлявыполненияследующихопераций:

золотыхмедалей.Ктомумоменту,когдатыбудешьчитатьэтистроки,итоги

•  добавлениеновоговеб-фильтра(метод Add);

олимпиадыбудутужеподведены.Ивэтомпланеятебенемногозавидую.

•  изменениепорядкаследованиявеб-фильтроввколлекции(методы

Носейчас,камрад,яскажутебевотчто.Почемувсеэтилюдисталилучши-

MoveDown и MoveUp);

мивмиреспортсменами?Впервуюочередь,потомучтоунихестьбольшая

•  удалениевеб-фильтраизколлекции(метод Remove).

цель—олимпийскоезолото.Непростоцель—обогнатьсоседаВаську

Инапоследок—финтушамиввидеответанавопрос,который,скореевсего, илисброситьпятькилограммлишнеговеса.Анастоящаябольшаяцель.И

ужедавнозаселвтвоейголове.Можнолизарегистрироватьфильтрили

поверьмне,вэтомполовинауспеха!Чтосамоеудивительное,такойподход

другоерасширениеИсывручную?Отвечаю—можно.Именясовершенно

действуетвлюбойсфереприложениятвоихусилий.ЕслиутебяестьБОЛЬ-

неинтересует,зачемтебеэтонужно:).

ШАЯЦЕЛЬ,успехнеотвратим.Таквыпьемжезанашибольшиецели:). z

xàêåð 09 /117/ 08

111

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

w Click

to BUY

 

>> coding

 

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

Игорь Антонов

/ http://vr-online.ru /

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Мобильный

сишарп

Осваиваем кодинг пол Windows Mobile 6

Добрые дяди из Apple привыкли решать за пользователя, какое ПО и какие опции ему нужны. Что ж, это выбор их пользователей. Мы же с тобой берем… и просто сами кодим то, что нам нужно. Старая добрая Винда была и остается другом юзеров и программистов, выбирающих свой собственый путь.

WinMobile вчера

Ещебуквальнонескольколетназадмобильнаяплатформастрадала дефицитомпрограммногообеспечения.Трудноповерить,но,чтобынайти нужнуютулзу,приходилосьнехилопопотеть.Апотомещеразнапрячьсяв попыткахотыскатьзаветныйкрэк(Странно,авродевсенеплохонаходи- лось,—Прим.Dr.Klouniz).Отсутствиесофтаобуславливалосьтем,чтодля разработкипрограммподновуюплатформунебылоудобнойIDE.Да,был могучийVisualC++,вкотором,еслимненеизменяетпамять,былисоответствующиемастера.Но,ксожалению,ихвозможностейнехватало.Когдав 2003годуяпопробовалзамутитьпервуюпрограммудляКПК,тосразупонял, чтомоихнервовнехватитдляинтимныхотношенийсужаснойVisualStudio. ПослеDelphiэтасредакажетсяужбольнонепродуманнойинепонятной. Такоечувство,чтопересаживаешьсяс«мерса»на«Волгу».

WinMobile сегодня

СегодняWindowsMobileсильнопреобразилась.Онадорослааждошестой версииитеперьееможносчитатьдействительнокомфортнойиудобнойОС. Этобылодостигнутокакзасчетулучшениявнешнеговида,такизасчетупрощенияпроцессаразработкисофта.Сейчасуженесоставляеттруданайти продвинутыйпочтовикилинавороченныйтекстовыйредактор.Болеетого, многиеразработчикиужевзялизаправиловыпускатьмобильныеверсии своихнастольныхпродуктов.ДляWindowsMobileдавнопоявилиськлоны

WinRAR,TotalCommander,WinZIP,MSOfficeит.д.Появлениебольшого

количествапрограммобъясняетсявпервуюочередьразвитиемплатформы.NET.Создаватьсофтнабазеэтойтехнологиичрезвычайнопросто

—иоченьпривычнодлякодеров,которыевырослинатакихязыкахкак Delphi/C++Builder.ПоследниеверсииVisualStudioсловнопереродились: онисталиудобнымиипоистинефункциональными.Приготовься,врамках этойстатьимысовершимнебольшойтрипвволшебнуюимногоцветную странуWM6.0.

Дорожный чемоданчик

Отправляясьвпутешествие,нельзязабыватьпровещипервойнеобходимости.ВыбросиизсвоегопоходногочемоданчикапроверенныйвременемDelphi,вэтотразоннепригодится.ВместонегодостаньVisualStudio (версиювыберикакможносвежее;личнояотдаюпредпочтениесамой последней—2008).ПомимостудиинамтакжепотребуетсяSDKдляработы сфункциями,характернымидлякоммуникаторов—sms,телефонияит.д.И SDK,исамуVSтывсегдаможешьслитьсwww.microsoft.com.

Время — деньги

Будемсчитать,чтотыуспешноскачалиустановилнужныйSDK,аэтозначит, чтоможнодвигатьсядальше.ЗапускайVisualStudioисоздавайновыйпроектдляVisualC#типаSmartDevice.Сразупослевыборатипапроектаперед тобойдолжнопоявитьсяокно,похожеенато,чтоизображенонарисунке1.

Вэтомокнетебенадовыбратьплатформу(Targetplatform),длякотороймы

112

xàêåð 09 /117/ 08

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

>> codingto BUY

 

 

 

 

 

 

 

 

 

w Click

 

 

 

 

 

 

m

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

 

.

 

 

 

 

 

.c

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

 

-x cha

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рисунок 1. Выбор шаблона для проекта

Рисунок 2. Чистый проект с необычной мордашкой

Рисунок 3. Привычная глазу форма

планируемсоздаватьприложение,атакжеверсию.NETФреймворка(.NET CompactFrameworkversion)ишаблонприложения(Templates).Длянаших примероввкачествеплатформыустановиWindowsMobile5.0Smartphone SDK(еслитыкачал6 юверсиюSDK,товыбирайименноее).Снейтебебудут доступнывсенеобходимыепространстваимендляработысоспецифическимифункциямикоммуникаторов/смартфонов.ВерсиюФреймворкастоит выбирать,исходяизтой,котораяустановленанатвоемдевайсе.Например,

намоемкоммуникатореToshibaPortegeG900тусуется.NETFramework2.0,

поэтомуявыбралименноэтуверсию.Внимание!Еслинатвоемустройстведосихпорустановленаперваяверсия.NETFramework,тобегомна microsoft.comискачивайхотябывторую.Перваяужбольносильноурезана впланефункционала.Все,теперьостаетсятольковыбратьшаблондля нашегоприложения.Длясегодняшнихпримеровнамвполнеподойдет

DeviceApplication.Клацай«Ок»—иVisualStudioсгенерируетновыйпустой проект(рисунок2).

ПоумолчаниюVSсоздаетчистыйпроектдлямобильныхустройствсоскиномввидеэтогосамогодевайса.Поправдеговоря,«дизайнить»формув такомвиденеоченьудобно,поэтомупотрудисьсразуотключитьотображениескина.Сделатьэтоможно,кликнувправойклавишеймышипоформеи выбраввконтекстномменю«ShowSkin».Послеэтогонехитрогодействия тыувидишьболее-менеепривычныйвидформы(рисунок3).

Пустойпроектготовинасталовремяпривестиеговрабочийвид.Готовь мышку,сейчасмыбудемраскидыватьэлементыуправления.Сегоднямы разберемнеодин,асразунесколькопримеров.Длятакого«проекта»нужна соответствующаяформа.Кстати,вариантаформыскучейзакладокядля себяненашел.Поэтомусоветуютебенезаморачиватьсяипойтитемже путем,чтоия—броситьирастянутьповсейформекомпонентTabControl,а затемсоздатьвнемпятьзакладок:

Получаемпроцессы

privatevoidGetProcList()

{

Cursor.Current=Cursors.WaitCursor; lvProcessList.Items.Clear();

process_list=TaskManager.Process.GetProcesses();

foreach(TaskManager.Processprocinprocess_list)

{

ListViewItemNewItem=newListViewItem (proc.ProcessId.ToString()); NewItem.SubItems.Add(proc.ProcessName); NewItem.SubItems.Add(proc.ThreadCount.ToString()); lvProcessList.Items.Add(NewItem);

}

Cursor.Current=Cursors.Default;

}

•  ОтправкаSMS; •  Процессы;

•  Файловыйменеджер; •  Dialer;

•  Полезности.

Думаю,назначениезакладокпояснятьненужно.Всеитакочевиднопоих названиям…Что?Тебеинтересно,чтоэтозазакладка«Полезности»?OК, сейчасобъясню.Здесьрасположенонесколькокнопок,которыевыполняют некоторыеполезныедляпользователяилизападлостроителядействия: поворотэкрана,выключение/перезагрузкасистемы.Мойвариантоформ- лениятыможешьувидетьнарисунках4-7.

Напишите письмецо…

Сдизайномформыпокончено,порапереходитьккодингу.Первое,чему мысегоднянаучимся—отправлятьSMS.Этимикороткимисообщениями пользуетсякаждыйизнас,аразтак,неплохобынаучитьсяотправлятьих программно.Зачем?Целимогутбытьразными.Например,некоторыенаосновеполученныхзнанийсмогутзакодитьпростенькуюпрограммку,которая будеттранслитерироватьвеськириллическийтекст,темсамым,позволяя сэкономитьсвоикровныенаотправкеSMS.Другиемогутчерезsms«выводить»свражескойтерриторииразличнуюполезнуюинформацию.Итак, создайобработчиксобытиядляоднойединственнойкнопкиснадписью «отправить»инапишивнемследующийкод:

if (textBox1.Text != ""){

SmsMessage mymessage = new SmsMessage(); //вот здесь можно добавлять кучу получателей

mymessage.To.Add(new Recipient(textBox1.Text)); mymessage.RequestDeliveryReport = cbReport.Checked; mymessage.Body = textBox2.Text;

try

{

mymessage.Send();

MessageBox.Show("Сообщение успешно отправлено!", "Информация!");

}

catch

{

MessageBox.Show("При отправке сообщения возникла ошибка!", "Ошибка!");

}

}

Ахтунг!Х-релиз!

НанашемдискетысможешьнайтиполноценныйХ-релизфай- ловогоменеджера,заботливоподготовленныйивыложенный авторомстатьи.

xàêåð 09 /117/ 08

113

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

w Click

to BUY

 

>> coding

 

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

 

 

 

 

 

Рисунок 6. Путеводитель по файлам

Рисунок 4. Простая

 

 

 

 

 

 

 

 

 

форма для отправки

SMS

 

 

 

 

 

 

Коданемного,такчтобыстренькопереписывайивозвращай-

 

 

 

сясюдазаразъяснениями.Всамойпервойстрочкеяпро-

 

 

 

веряю,заполненолиполесполучателем(еслинет,тоделать

 

 

 

ничегоненужно).Учти,чтодлядемонстрационногопримера

 

 

 

такойпроверкивполнедостаточно,нодлясозданияреального

 

dvd

приложенияеебудетмаловато.Еслитырешишьвбудущем

На нашем DVD

закодитьтулзудляотправкисообщений,тоярекомендуютебе

ты найдешь весь

проверятьномерполучателяспомощьюрегулярныхвыраже-

необходимый стафф

ний.Толькотакможнобытьуверенным,чтоэтодействительно

для статьи — сорцы,

номер,анечехардаизбуквицифр.Проверивномерполу-

бинарники, софт.

чателя,можнопереходитьнепосредственнокотправке.Для

 

 

 

отправкиSMSвSDKестьготовыйкласс— SmsMessage.Как

 

 

 

иполагается,передтемкакначатьработатьсклассом,нужно

 

 

 

создатьегоэкземпляр.Именноэтояиделаювовторойстрочке

 

 

 

кода.Инициализировавкласс,нужнонетеряться,асразу

 

 

 

начатьзаполнятьегосвойства.Ксчастью,ихнемного:

 

 

 

•  TO—коллекцияполучателей.Вэтомсвойстветыможешь

 

warning

установитькакодного,такинесколькихполучателей.

Рискну напомнить,

•  RequestDeliveryReport—отчетодоставке.Есливэтом

что использовать

свойствеtrue,топослеотправкисообщениябудетзапрошен

свои знания нужно

отчет.

только в мирных

•  Body—текстсообщения.

целях — звонки на

Разобравшисьсосвойствами,можнопереходитькметодам,а

платные номера,

методвсегоодин— Send().ВпримеревызовметодаSend()

отсылка приватной

язаключаювблокоператоровисключительныхситуаций.Это

информации по SMS

делаетсянаслучайнеожиданныхошибок.Попробуйсейчас

не приветствуется

сохранитьвнесенныеизмененияисобратьпроект.Неспеши

законодательством.

паниковать,еслиVSнервноматерится.Простодобавьновое

Вся ответственность

пространствоимен(Microsoft.WindowsMobile.PocketOutlook)

— на тебе лично!

—иопятьпопытайсясобратьпроект.Что,нехочет?Ok,don’t

 

 

 

worry.ЗайдивменюProjectAddReference.Впоявившемся

 

 

 

окневыберинужнуюсборкуинажми«ОК».Теперьпроект

 

 

 

долженуспешнособраться.Можешьужесейчасзалитьсвеже-

 

 

 

испеченнуюпрогувсвойдевайсипротестировать.Аяначну

 

 

 

разбиратьследующийпример.

 

 

 

 

Мониторим процессы

 

 

 

 

 

 

 

 

 

 

 

Намойвзгляд,одинизглавныхминусовWinMobile—это

 

 

 

отсутствиевстроенныхсредствдляпросмотраспискаактивных

 

 

 

задачилипроцессов.Внаписаниитакойтулзынетничегослож-

 

 

 

ного,нопочему-томногиепрограммистыпытаютсянеплохо

 

 

 

заработатьнаподобныхпрограммах.Мненаглазапопадался

 

 

 

продвинутыйдиспетчерзадачскучейразныхненужных

 

 

 

функцийпоцене$30.Нехило?Личнодляменяэтомного,исвои

 

 

 

честнозаработанныеденежкияпредпочитаютратитьначто-

нибудьдругое.Итак,создавайобработчиксобытия Click()длякнопки«Обновить»,расположенной навторойзакладке.Напишиздесьвсегоодну строчкукода:

GetProcList();

Кодсамойпроцедурытыможешьнайтинасоответствующейврезке.Начинайегопереписывать, аяпотружусьобъяснить,чтовнемпроисходит.

Взглянувналистинг,тынавернякаудивился

—дляполученияспискапроцессовпотребова- ласьвсегооднастрочка(переборидобавление каждогоизнихвListViewнесчитаем).Еслиты хотьразпробовалкодить«диспетчерпроцессов»подWin32(конечнокодил;][акеруженераз писалобэтом),тонавернякапомнишь,чтодля полученияспискаактивныхпроцессовприхо- дилосьвызыватькучуAPI-функцийисовершать многотелодвижений,—атутвсекак-топросто

ибыстро.Нонетакпросто,каккажетсянапервыйвзгляд!

Строка«process_list = TaskManager.Process. GetProcesses()»говоритотом,чтополучениепроцессов происходитпосредствомвызоваметода GetProcess() класса Process.Класс Process являетсяразработкой CristianForsbergи,благодаряему,работаспроцессами превращаетсявсплошноеудовольствие.Точнее,водну строку.Все,чтонамтребуется,—этополучитьсписоквсех процессовпосредствомвызовавсего-навсегоодногометода

—GetProcess().Послеэтогоостаетсятолькозапустить переборвциклеивытащитьинформациюокаждомизних. Всюэтуинформацию(количествопотоков,имяпроцесса,pid) яидобавляюв ListView.Остальнуючернуюработуделает хорошопродуманныйкласс.Кстати,модульсклассомтыможешьвзятьснашегодиска,апослевыходажурналавсвет— и наwww.vr-online.ruбудетдоступеннемногопереработанный вариантэтогокласса,свозможностьюполучатьпутькфайлу процесса.Будемсчитать,чтосписокпроцессовунасполучен. Теперьнужнонаучитьсяимуправлять—убиватьлишние.Для решенияэтойнетруднойзадачкиукласса Process есть методKill().Реализацияпроцессазавершения—ниже:

TaskManager.Process proc; proc = process_list[

lvProcessList.SelectedIndices[0]];

proc.Kill();

Силамиэтогонехитрогокодаявыковыриваювыделенный процессипростовызываювышеозвученныйметод.Простодо безобразия!

Файловый менеджер

Файловыйменеджер—тулза,безкоторойянемогупредста- витьниодногосвоегорабочегодня.На«большом»компея комфортноюзаюбесплатныйUnrealCommander(практически клонTotalCommander’a).Снедавнеговременинеобходимость вфункциональномфайловомменеджерепоявиласьипри работенакоммуникаторе.Опятьже,янесталзаморачиваться сRescoExplorerиегомаленькимидрузьями,арешилпопробоватьзакодитьвсесамостоятельно.Создайпустуюфункцию FileListинаполниеетело(Хе-хе,—Прим.Dr.Klouniz)кодом изсоответствующейврезки.Какобычно,возвращайсяза разъяснениями.

Всамомначалеяменяювидкурсора.Получениесписка файлов—делонебыстрое,особеннонамобильныхдевай-

114

xàêåð 09 /117/ 08

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

E

 

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

d

 

 

 

F

 

 

 

 

 

t

 

 

 

D

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

NOW!

o

 

>> codingto BUY

 

 

 

 

 

 

 

 

 

w Click

 

 

 

 

 

m

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

o

 

 

 

.

 

 

 

 

.c

 

 

 

 

p

 

 

 

g

 

 

 

 

 

 

df

 

n

e

 

 

 

 

 

 

-x cha

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рисунок 7. Звонилка :)

 

Рисунок 8. Путешествие в страну файлов эму-

 

Рисунок 5. Продвинутый диспетчер процессов

лятора

 

 

сах.Поэтому,чтобылишнийразнесмущатьпользователя,лучшевыбрать привычныйкурсордлятормозныхоперацийиспатьспокойно.Послетакой хитройподготовки(нервнойсистемыпользователя)ничтонепомешаетнам перейтинепосредственнокполучениюспискафайлов.Сначалаполучим списокдиректорий(пустьонибудутсверху,какипринятововсехфайловых менеджерах),аужепослеэтогопробежимсяпофайлам.Дляполучения директорийяиспользуюкласс Directory.Уэтогоклассаестьметод GetDirectories(),позволяющийполучитьсписокпапокпопереданномувкачествеединственногопараметрапути.Получивсписокпапок, ихобязательнонужнодобавитьвконтейнер-коллекцию,чтобыпотомих можнобылоудобноотсортировать(foldersList.Sort()).Отсортировавсписокдиректорий,можноприступатькдобавлениюнайденных папокв ListView.Последобавленияпапокяприступаюкполучению файлов.Алгоритмполученияспискафайловточнотакойже,поэтомуя нестанузаострятьнанемвнимание.Теперьсоздайобработчиксобытия Click() длякнопки«Перейти».Поеенажатиюмыбудемзапрашивать содержимоеконкретнойпапки.Все,чтонамтребуетсянаписатьвэтом обработчике—вызовфункцииFileList()которуютыможешьнайтина

дискеЕслисейчасзапуститьпример,тоужереальноначатьпутешествиепо файловойсистеме.Наберивполедлявводапутилюбойадрес(например, MyDocuments)инажминакнопку«Перейти».Еслиприпереписывании листингатынедопустилошибок,точерезмгновение ListView должен заполнитьсяспискомфайлов(рисунок8).

Итак,теперьнашменеджерумеетотображатьсписокфайлов,нокое-чего емуявнонехватает:какойможетбытьфайловыйменеджербезвозможностивыполнениястандартныхопераций(созданиепапок,копирование иудалениефайлов,запускапрограммы)?Поэтомунамволей-неволей,но придетсярасширятьфункционал.OК,начнемсудаленияфайлов.Удалить файлнепроблема(гораздотруднеееговосстановить:)).Отнастребуется лишьвызватьметод Delete() класса File.Вкачествеодногоединственногопараметраметодпринимаетполныйпутьктомуфайлу,который долженбытьудален.Списокфайловунасв ListView.Естьунасипутьк папке,вкотороймыработаем(tbPath).Значит,все,чтонамнужно—это прибавитьимяфайлакполномупутикпапке,вкотороймысейчаснаходимся,ивыполнитьметод Delete():

File.Delete(tbPath.Text +

listView1.Items[listView1.SelectedIndices[0]].Text);

Копированиефайлареализуетсяаналогичнымспособом,носоднимотли- чием—здесьтребуетсявызыватьнеметод Delete(),аметод Copy(), которомунужнопередатьдвапараметра:

•  полныйпутькфайлуисточнику; •  полныйпутькфайлуприемнику.

xàêåð 09 /117/ 08

Определитьфайл-источникможнотакимжеспособом,какиприудалении, поэтомуещеразприводитькодянебуду.Папкисоздаютсяпосредствомвызоваметода CreateDirectory().Методпринимаетвсегоодинпараметр

—путьксоздаваемойпапке.Каквидишь,встроенныеклассысущественно упрощаютработусфайламиипапками,позволяясовершеннозабытьо неудобномиспользованииWindowsAPI.Совсемдругаяисториясзапуском файлов.

Такужполучилось,норазработчикиC#неснабдилинасудобнымклассомдлязапускавнешнихпрограмм.Печально,нонесмертельно.Уже известныйнамCristianForsberg,помимоклассадляработыспроцессами, любезнопредоставилнасудобщественностикласс ShellExecute, позволяющийстартоватьпрограммы.Подключимодульсклассомксвоему проектуи,вызвавметод Start(),передайемупутькзапускаемомуфайлу. Дальнейшее—работакласса.Янестануприводитьпримеркодазапуска, таккаквнемничегонеттрудного.Вкрайнемслучае,наDVDтебяждет полныйисходниксовсемирассмотреннымиклассами.

Позвони мне, позвони

МыужепознакомилисьсотправкойSMS,получениемпроцессов,выполнениемоперацийсфайлами…дошелчередидотелефонии!Яспециально оставилэтоназакуску,ведьблагодаряклассамработатьснейпросто—и писатькучукоданепонадобится.Небудумногословным,простовзглянина этоткод:

PhoneNewPhone = new Phone();

NewPhone.Talk(tbTellNumber.Text, false);

Этихтрехстрочекдостаточно,чтобысовершитьзвонокпономеру(конечно, платному!:)),введенномувполе tbTellNumber.Второйпараметр(false) методаTalkговоритотом,чтономернужнонабиратьсразуже,неожидая разрешений.

The End

ПрограммироватьдляWindowsMobile,используятехнологию.NET,чрезвы- чайнобыстроиудобно.Сегодняшниепримеры—лишнеетомуподтверж- дение.Обративнимание,мырассматривалитолькодемонстрационные примеры,нонаихосновевполнереальнонаписатьнастоящиехакерские тулзы.Например,тыбезтрудасможешьотправлятьсдевайсавладельца всюнужнуютебеинфупосредствомsmsилиустроитьсамуюнастоящую прослушкусредьбеладня(автоматическинабралнужныйномервнужное времяи...).Ипускайпотомжертвавспоминает,какеетелефонсмогпозвонить,стоянаблокировке.Наэтойславнойнотеяхочузакончитьсвоюсказку ипопрощатьсястобой.Удачивнелегкихкодерскихделах! Какобычно,все твоивопросыяждунамыло:antonov.igor.khv@gmail.com.z

115

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

to BUY

 

 

w Click

 

 

 

>> coding

 

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

Крис Касперски

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

трюки открыса

Сишные трюки

Доброкачественная инициализация переменных — явление редкое, можно даже сказать, уникальное. Анализ открытых исходных текстов и дизассемблирование закрытых двоичных модулей показывает, что большинство программистов не имеют никакого представления о внутренней кухне компилятора, совершая грубые ляпы, о которых мы сейчас и поговорим!

01Стек,статикаидинамика

Чемотличаютсялокальныеавтоматические переменные от локальных статических/глобальных? Да много чем отличаются… так, навскидку, без учебника и не вспомнишь, что статические/глобальные переменные инициализируются «самостоятельно». Незнание или игнорирование этой особенности приводит к двум распространенным ошибкам.

Код вида int x = 0; foo(){… return x;}выглядит ужасно непрофессионально (x гарантировано обнуляется компилятором путем помещения его в секцию данных, тогда как явное присвоение нуля

— выполняется уже в реальном времени, напрягая процессор лишними машинными командами). Неприятно, конечно (свидетельство того, что программист умных книжек не читал), но не смертельно.

А вот другая ошибка, совершаемая уже теми, кто учебники все-таки читает, но не дочитывает — «foo(){ static int x;… return x;}».

Казалось бы, что здесь неправильного? Ведь переменная x гарантировано равняется нулю и инициализировать ее «вручную» необязательно! Да, верно, x будет равна нулю, но… — лишь при первом выполнении функции. При всех последующих в ней останется знание, которое было на момент выхода из функции foo(), что рискует развалить всю программу, а потому инициализировать статические переменные все-таки нужно. Если, конечно, они не задействованы для умышленного сохранения значений и использования их в последующих вызовах функции. Явное присвоение значений — расточительная операция в планепроцессорных тактов и объема кода, особенно когда переменных много. Намного выгоднее передать функции memset указатель на начало блока статических (глобальных) переменных и проинициализировать их одним махом. Экономия становится заметной даже при десятке переменных. Следуя духу и этикету языка, следовало бы загнать все переменные в единую структуру, чтобы обеспечить гарантированный порядок их

размещения в памяти… однако, работать со структурами жутко неудобно, да и не нужно. Статические и глобальные переменные размещаются в памяти в порядке их объявления в программе, и нам достаточно лишь получить указатель на первую и последнюю переменные. С локальными автоматическими переменными этот трюк, увы, не работает. В общем случае они размещаются в порядке, обратном обращению к ним (как

компилятор встречает обращение к локальной переменной, он

забрасывает ее на верхушку стека и потому последняя используемая переменная оказывается первой в стековом кадре). Но из этого правила существует множество исключений.

Оптимизирующие компиляторы стремятся выкинуть максимум локальных переменных, загнав их в регистры или вычисляя эффективные значения еще на стадии компиляции. А последние версии GCC и MS VC, вдобавок, бьют стековый фрейм на две части, складируя в одну буфера, а в другую — скалярные переменные и указатели для затруднения атак на переполнение. Как следствие, мы уже не можем инициализировать локальные переменные через memset. То есть, еще как можем! Достаточно поместить их в структуру! Неудобно, но на какие жертвы не пойдешь ради оптимизации! Только в этом случае она будет называться «пессимизацией», поскольку компилятор не может оптимизировать члены структуры так же свободно, как обычные локальные переменные. Некоторые компиляторы поддерживают нестандартный ключ, предписывающий выполнять инициализацию стекового кадра при его открытии. На пер-

вый взгляд, очень полезная штука. Нопользоватьсяейкатегорически нерекомендуется(поэтому автор даже не будет говорить, что это за ключ такой и кто его поддерживает), поскольку в этом случае весь стековый фрейм инициализируется целиком, даже если содержит массивы, явно инициализируемые по ходу программы ненулевыми значениями. И это еще мелочи — подумаешь, двойное обращение к памяти! Гораздо хуже, когда программист, закладывающийся на то, что инициализацию локальных переменных выполнит компилятор, публикует код своей

программы или использует его фрагменты в другом проекте, забыв о том, что там локальные переменные уже не инициализируются!

Вывод:безособойнуждымассивылучшевстекенеразмещать. Ис-

пользуйте для этого статическую память или кучу. Первая инициализируется при загрузке исполняемого файла в память. Вторую программист инициализирует явно, когда это действительно необходимо. На самом деле, менеджер кучи, встроенный в операционную систему, всегда выполняет инициализацию блоков памяти перед их отдачей прикладной программе. Однако, при переходе на прикладной уровень — уровень библиотек и RTL — мы, в общем случае, не можем сказать, выполняется автоматическая инициализация или нет, а потому лучше не рисковать, особенно, если программу планируется переносить на другиеплатформы или компилировать более чем одним компилятором.

116

xàêåð 09 /117/ 08

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

E

 

 

 

 

X

 

 

 

 

 

-

 

 

 

 

d

 

 

F

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

NOW!

o

>> coding to BUY

 

 

 

 

 

 

 

w Click

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

o

 

 

.

 

 

 

 

.c

 

 

 

p

 

 

 

g

 

 

 

 

 

df

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

02Строкиимассивы

А вот другая популярная ошибка, встречающая практически повсеместно и ставшая неофициальным стандартом де-факто:

Классическаяошибкаиспользованиялокальныхбуферов

foo()

{

char s[]="hello, sailor!\n";

bar(s);

}

Что не так — вполне приличный код! А если подумать? Компилятор размещает строку «hello, sailor!\n» в секции данных (хотя тут возможны вариации), что происходит на стадии компиляции. А затем копирует ее в локальный буфер при каждом вызове функции уже на стадии исполнения! Таким образом мы получаем двойной перерасход памяти и довольно ощутимые тормоза, которые ничем не оправданы, поскольку функция bar не изменяет строку s. Поэтому перед «char s[]» необходимо поставить «static» или вынести s в глобальные переменные. Впрочем, настоящие проблемы начинаются, когда программист (причем, вменяемый, трезвый и совсем не обкуренный) пишет код вида:

Ужас,летящийнакрыльяхночи

foo()

{

int matrix[100][100]={{1,2,3},{4,5,6},{7,8,9}};

}

А здесь что не в порядке? Программист создает законный двухмерный массив, инициализируя малую его часть (очевидно, что остальные ячейки предполагается заполнить по ходу выполнения функции foo). Согласно Стандарту, здесь инициализируется весь массив, причем, ненулевые ячейки компиляторы инициализируют индивидуально, расходуя на каждую из них, по меньшей мере, одну машинную инструкцию. Это в идеале, а на практике компилятору MS VC необходимо 27 команд, чтобы справиться с вышеприведенным массивом. Хорошего мало, особенно, если функция foo вызывается больше одного раза. Стек не резиновый и обычно (читай — по умолчанию) потоку достается порядка 1 Мб.

За бездумное размещение массивов в стеке давно уже пора расстреливать. Ключевое слово «static», размещенное перед «int matrix», сокращает потребности в памяти и увеличивает скорость выполнения программы в несколько раз! А как быть, если статический массив нас «ну никак не устраивает»? Допустим, массив должен инициализироваться при каждом вхождении в функцию. Нет ничего проще! Размещаем исходный массив в глобальной или статической переменной, а при каждом вхождении в функцию копируем его во временный буфер, выделяемый из пула динамической памяти. Копирование, осуществляемое посредством memcpy, намного быстрее поэлементной инициализации (напоминаю, что статические массивы инициализируются на стадии компиляции, не транжиря процессорное время).

Оптимизированныйвариантработысмассивом

foo()

{

static int _matrix[100][100]={{1,2,3}, {4,5,6}, {7,8,9}};

int (*matrix)[100][100];

matrix= (int(*)[100][100]) malloc (sizeof(matrix)); if (!matrix) return -1;

else memcpy(matrix, _matrix, sizeof(matrix));

free(matrix);

}

Конечно, куча не лишена недостатков. Выделение динамической памяти занимает больше времени, чем стековой. Динамические блоки необходимо освобождать и еще обрабатывать ситуацию с нехваткой памяти, проверяя успешность завершения malloc. При этом: а) динамической памяти, как правило, имеется в избытке и отсутствие проверки, в общем-то, не фатально; б) никто не гарантирует успешность выделения стековой памяти, а универсального способа проверки (работающего во всех системах) нет и остается только молиться, надеясь на то, что стека все-таки хватит.

Короче, существует тысяча и одна причина для отказа от использования стековой памяти при работе со строками и массивами.

03Массивы,начинающиесянеснуля

В прошлых выпусках «Трюков» мы уже рассматривали способы организации массивов, начинающихся, например, с единицы, что особенно удобно при переносе программ с Паскаля и Фортрана на Си. Увы, те способы не работали с Си++ и не позволяли создать массивы, начинающиеся с произвольного индекса, например, 0x69.

Предложенный ниже прием полностью совместим с Си++, однако работает не на всех платформах. Руководящая идея проста, как два весла: получаем указатель на массив и уменьшаем его на величину начального индекса. Так, мы можем создать массив 6...9:

Созданиемассиваp_array[6..9]

foo()

{

static int x_array[9 - 6]; int *p_array = x_array - 6;

return 0;

}

Аналогичный трюк работает и со стековыми массивами (хотя, как мы уже говорили выше, в стеке массивы лучше не размещать), и с динамическими. Нужно только не забывать увеличивать указатель на массив при освобождении памяти. Это не украшает программу и чревато появлением ошибок — но за любые удобства в этом мире приходится чем-то платить.

Другое существенное ограничение заключается в том, что при вычитании начального индекса из указателя мы рискуем нарваться на «заворот». Впрочем, во всех современных операционных системах и стек, и куча, и секция данных лежат довольно далеко от нулевого адреса. А вот создавать массив типа 666666...666669 — уже опасно.

На одной системе (или даже версии системы) это может сработать, на другой — уже нет. z

xàêåð 09 /117/ 08

117

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

E

 

 

 

 

X

 

 

 

 

 

-

 

 

 

 

d

 

 

F

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

to BUY

 

 

w Click

 

 

>> phreaking

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

o

 

 

.

 

 

 

 

.c

 

 

 

p

 

 

 

g

 

 

 

 

 

df

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

Генри Шеппард

/ www.sheppard.ru /

Мышечные

импланты

>>Суперсила для хакера

Подавляющеечислолюдейнеотличаютсянеточтобыатлетическим телосложением,ноивообщенеобладаютсколько-нибудьзаметной физическойсилой.Покрайнеймере,нетакой,чтобыпротивостоять, скажем,тремпротивникамодновременно.Атакхочетсяпосрамить постановочныетрюкиДжекиЧана!

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

В чем сила, брат?

Напервыйвзгляд,мышцы—лажаифигня(посравнениюспочками, печеньюи,темболее,головныммозгом,гдеисамыймаститыйученый непонимаетиполовиныпроцессов).В«мясе»простокакие-товолокна, которыесокращаются...ивсе,пожалуй.Нопростотамышцобманчива!Ко-

нечно,всеониизученыиподсчитаны.Давотбеда—досихпорневыяснен главныймомент,интересующийбодибилдеров:почемужемышцысокращаютсяизасчетчегорастут.Аеслибыисследователиэтовыяснили,тогда мыбымоглиштамповатьШварценеггеровпоточно-вахтовымметодом!

Вспомним морально устаревшие боевики с Лундгреном или Ван Даммом. Несмотря на розовую мечту сыграть Гамлета, эти мордовороты обязательно попадали в оборот жадного продюсера. Тот всенепременно покупал идиотский сценарий про суперсолдата, напичканного всякими усилителями и имплантами, которые позволяли валить всех одних пальцем…

Современнаятехнологиядавноужедогналабольшинствозадумоки фантастов,исценаристов.Кардиостимуляторысуществуютболеетридцатилет,спасаяжизнитысячамлюдей.Лечениепоставленонапотоки сталорутиной.Технологиявылизанадоблеска,такчтопоразадуматьсяо расширениисферыпримененияимплантированныхстимуляторов.

Мясо с кровью, «по-профессорски»

Для начала штудируем теорию. Не все мышцы устроены одинаково. Вообще говоря, из почти семисот мускулов человеческого тела (многие из них парные) «невооруженным глазом» можно увидеть лишь малую часть. Делятся они на три основных типа: веретенообразные (или ременные), перистые и сходящиеся (веерообразные). Ременные мышцы крепятся к сухожилиям с обоих концов и состоят из мышечных волокон, расположенных параллельно друг другу. Примером может служить, например, бицепс предплечья. Волокна перистых мышц крепятся к

118

xàêåð 09 /117/ 08

Соседние файлы в папке журнал хакер