В этой статье я рас­ска­жу о том, как соз­дать прос­тое при­ложе­ние — заготов­ку панели инс­тру­мен­тов для рабоче­го сто­ла Windows. По ходу дела мы вспом­ним Win32 API, раз­берем­ся, как его исполь­зовать на язы­ке ассем­бле­ра, и поз­накомим­ся с Flat Assembler, который ста­нет для нас основным инс­тру­мен­том раз­работ­ки.
 

Нет в мире совершенства

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

Дефект монитора в виде горизонтальных полос
Де­фект монито­ра в виде горизон­таль­ных полос

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

Ка­кие еще оста­ются вари­анты? Знаю по опы­ту, что офи­циаль­ный сер­вис, ско­рее все­го, выс­тавит заг­радитель­ную цену, а отда­вать боево­го товари­ща в очу­мелые руч­ки кус­таря‑оди­ноч­ки совесть не поз­воля­ет. Наибо­лее здра­вой кажет­ся мысль пой­ти в бли­жай­ший магазин, купить новый монитор и не дурить голову ни себе, ни читате­лям. Имен­но так я бы и пос­тупил, если бы монитор не работал сов­сем. Но он поч­ти работа­ет, и выб­расывать его поп­росту жал­ко.

А ведь если подумать, ремонт необя­затель­но пред­полага­ет вос­ста­нов­ление исходно­го качес­тва изде­лия — зачас­тую допус­кает­ся некото­рая утра­та пот­ребитель­ских свой­ств. Как, нап­ример, пос­тупа­ет хакер, обна­ружив в один прек­расный день дыру... нет, не в безопас­ности, а в любимых домаш­них брю­ках? Дос­тает свой тол­стый кошелек и спе­шит в бли­жай­ший бутик за новыми? Нет, он вспо­мина­ет уро­ки Марь­ван­ны и, при­меняя методо­логию «впе­ред игол­ка», нак­ладыва­ет зап­латку! Или дру­гой при­мер. В не менее прек­расный день ин­женеры NASA обна­ружи­ли, что основная антенна ради­освя­зи запущен­ного к Юпи­теру зон­да не рас­кры­лась пол­ностью. Раз­ве они бро­сили неис­прав­ное устрой­ство на про­извол судь­бы и обра­тились к пра­витель­ству за финан­сирова­нием нового? Нет, они про­яви­ли наход­чивость и тех­ничес­кую сме­кал­ку, в резуль­тате чего пусть и не без тру­да, но успешно про­вели мно­голет­нюю иссле­дова­тель­скую мис­сию.

 

Выбор цели и средства

Рас­смат­рива­емая в статье ситу­ация находит­ся где‑то меж­ду эти­ми край­ними слу­чаями. Наиболь­шие неудобс­тва опи­сан­ный дефект дос­тавля­ет при исполь­зовании раз­верну­тых на весь экран прог­рамм, потому что попада­ет либо на адресную стро­ку бра­узе­ра, либо на глав­ное меню при­ложе­ния. Исполь­зование же прог­рамм в окон­ном режиме, с под­гонкой их мес­тополо­жения пос­ле каж­дого запус­ка, гро­зит нер­вным расс­трой­ством. Я готов пожер­тво­вать частью полез­ной пло­щади экра­на, если изоб­ражение не будет попадать на дефек­тную область.

Ос­новная опе­раци­онная сис­тема на моем компь­юте­ре — Windows. Как исклю­чить полосу в вер­хней час­ти экра­на из дос­тупно­го прос­транс­тва рабоче­го сто­ла, что­бы окна при­ложе­ний при раз­верты­вании не попада­ли на нее? Идею мне под­ска­зала панель задач: она монопо­лизи­рует ниж­нюю часть экра­на и никог­да не перек­рыва­ется окна­ми прог­рамм. Может быть, дос­таточ­но будет прик­репить ее к вер­хней час­ти экра­на? Нет, во‑пер­вых, она не сов­сем под­ходит по раз­меру, а во‑вто­рых, сама при­обре­тает неп­ригляд­ный вид из‑за дефек­та. А нель­зя ли сде­лать «зап­латку» с такими же свой­ства­ми, но что­бы поль­зователь мог кон­тро­лиро­вать ее раз­мер и цвет?

Ока­зыва­ется, мож­но, и ответ быс­тро нашел­ся в спра­воч­нике по Win32 API — это па­нель инс­тру­мен­тов рабоче­го сто­ла. Нап­равле­ние работы про­ясни­лось, оста­лось выб­рать под­ходящий инс­тру­мент для ее выпол­нения. Основное средс­тво раз­работ­ки с исполь­зовани­ем Win32 API — ком­пилятор С. Но для вызова нес­коль­ких фун­кций опе­раци­онной сис­темы хочет­ся вос­поль­зовать­ся чем‑то более прос­тым и изящ­ным. Поэто­му я отпра­вил­ся в тем­ную кла­довую сво­ей памяти и нашел там пыль­ную шка­тул­ку с плос­ким мон­тажни­ком. Если кто‑то еще не догадал­ся, то так зву­чит по‑рус­ски Flat Assembler в вари­анте Яндекс‑перевод­чика. Уди­витель­но, но про­дукт, с которым я поз­накомил­ся еще в середи­не 2000-х, про­дол­жает жить и здравс­тво­вать.

 

Что умеет Flat Assembler?

Да­вай пря­мо сей­час раз­берем­ся со сре­дой, в которой будем работать. На стра­нице заг­рузки выбери архив с пос­ледней вер­сией сбор­ки для Windows, заг­рузи его и рас­пакуй куда‑нибудь на диск. В трех мегабай­тах пап­ки FASMW есть все, что нам пот­ребу­ется.

Соз­дай пус­тую пап­ку Appbar для рабоче­го про­екта и ско­пируй в нее исходный текст шаб­лона типово­го при­ложе­ния Windows FASMW\EXAMPLES\TEMPLATE\TEMPLATE.ASM. Запус­ти интегри­рован­ную сре­ду раз­работ­ки FASMW\FASMW.EXE и с помощью пун­кта меню File → Open... заг­рузи в нее этот файл. Обра­ти вни­мание, что в нашем рас­поряже­нии есть тек­сто­вый мно­гоокон­ный редак­тор с под­свет­кой син­такси­са ассем­бле­ра.

Текстовый редактор интегрированной среды FASMW
Тек­сто­вый редак­тор интегри­рован­ной сре­ды FASMW

Шаб­лон Windows-при­ложе­ния на ассем­бле­ре сос­тоит из сле­дующих основных час­тей:

  • за­голов­ка с ука­зани­ем фор­мата целево­го исполня­емо­го фай­ла и точ­ки вхо­да в при­ложе­ние;
  • сек­ции кода .text, где мет­ка start ука­зыва­ет коман­ду, с которой дол­жно начинать­ся выпол­нение прог­раммы;
  • сек­ции дан­ных .data, содер­жащей гло­баль­ные перемен­ные прог­раммы;
  • сек­ции импорта .idata, в которой перечис­лены исполь­зуемые прог­раммой динами­чес­кие биб­лиоте­ки и под­клю­чают­ся объ­явле­ния содер­жащих­ся в них фун­кций.

В целом текст прог­раммы дол­жен быть понятен любому, кто исполь­зовал Win32 API. Во‑пер­вых, сам API пре­дель­но прост. Парамет­ры всех фун­кций ожи­дают 32-бит­ных зна­чений аргу­мен­тов, а если дан­ные не укла­дыва­ются в этот раз­мер, то переда­ется 32-бит­ный ука­затель на мас­сив или струк­туру опять же 32-бит­ных зна­чений. Исклю­чение, пожалуй, толь­ко стро­ки. Воз­вра­щаемое фун­кци­ей зна­чение (нап­ример, код завер­шения) переда­ется через регистр EAX или, если оно пре­выша­ет 32 бита, через струк­туру, на которую ука­зывал один из аргу­мен­тов.

Во‑вто­рых, Flat Assembler на осно­ве сво­его набора мак­роинс­трук­ций пред­лага­ет син­такси­чес­кий сахар, который дела­ет исполь­зование API мак­сималь­но приб­лижен­ным к высоко­уров­невым язы­кам прог­рамми­рова­ния. Ска­жем, доволь­но слож­ный вызов фун­кции соз­дания окна опи­сыва­ется одной стро­кой:

invoke CreateWindowEx,0,_class,_title,WS_VISIBLE+WS_DLGFRAME+WS_SYSMENU,128,128,256,192,NULL,NULL,[wc.hInstance],NULL

Здесь invoke — это коман­да вызова под­прог­раммы в соот­ветс­твии с сог­лашени­ем STDCALL, CreateWindowEx — имя вызыва­емой API-фун­кции, а далее через запятую сле­дуют аргу­мен­ты в том поряд­ке, в котором они опи­саны в докумен­тации. С‑прог­раммис­ты могут счи­тать, что име­на всех перемен­ных здесь — это ука­зате­ли (_class, _title), для разыме­нова­ния которых исполь­зуют­ся квад­ратные скоб­ки ([wc.hInstance]). Отме­тим при­выч­ную «точеч­ную» нотацию дос­тупа к эле­мен­там струк­туры.

Опи­сание окон­ной про­цеду­ры WindowProc тоже не дол­жно выз­вать зат­рудне­ний:

proc WindowProc uses ebx esi edi, hwnd,wmsg,wparam,lparam
...
ret
endp

Сог­лашение Win32 API тре­бует, что­бы пос­ле воз­вра­та из про­цедур обратно­го вызова (callback-про­цедур) зна­чения регис­тров EBX, ESI и EDI были такими же, как и перед вызовом. Для это­го в заголов­ке при­сутс­тву­ет ука­зание на сох­ранение этих регис­тров в виде фра­зы uses ebx esi edi. А даль­ше через запятую идет спи­сок фор­маль­ных парамет­ров про­цеду­ры, которые соот­ветс­тву­ют докумен­тации.

Те­перь ты можешь ском­пилиро­вать и выпол­нить эту прог­рамму. Но сна­чала ука­жи путь к пап­ке с под­клю­чаемы­ми дирек­тивой include фай­лами в пун­кте меню Options → Compiler setup так, что­бы он соот­ветс­тво­вал фак­тичес­кому мес­тополо­жению FASMW\INCLUDE. Пос­ле это­го выпол­ни пункт меню Run → Run или прос­то наж­ми кла­вишу F9. Если все было сде­лано пра­виль­но, то в рабочей пап­ке Appbar появит­ся све­жесоб­ранный файл TEMPLATE.EXE, а на экра­не отоб­разит­ся кро­шеч­ное окно Win32 program template.

Настройка пути к подключаемым файлам
Нас­трой­ка пути к под­клю­чаемым фай­лам
 

Создание обработчика сообщения WM_CREATE

Со сре­дой раз­работ­ки разоб­рались, прис­тупим к работе над прог­раммой. Если рань­ше ты никог­да не прог­рамми­ровал панели рабоче­го сто­ла Windows, то сей­час самое вре­мя изу­чить докумен­тацию. Но перед этим хочу обра­тить вни­мание на основные момен­ты. Панель рабоче­го сто­ла не явля­ется каким‑то уни­каль­ным объ­ектом опе­раци­онной сис­темы. Роль панели может играть любое окно, соз­данное фун­кци­ей CreateWindowEx. Все средс­тва Windows, обес­печива­ющие фун­кци­они­рова­ние панели, сос­редото­чены в единс­твен­ной фун­кции SHAppBarMessage, с помощью которой мож­но:

  • уз­нать гра­ницы области рабоче­го сто­ла, в пре­делах которых мож­но раз­местить новую панель инс­тру­мен­тов;
  • за­резер­вировать на этой области учас­ток для раз­мещения новой панели;
  • ука­зать манипу­лятор (handle) окна с панелью, которо­му будут отправ­лять­ся сис­темные уве­дом­ления, свя­зан­ные с изме­нени­ем обста­нов­ки на рабочем сто­ле.

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

С помощью пун­кта меню File → Save as... сох­рани откры­тый в редак­торе файл под име­нем appbar.asm. В нашей прог­рамме панелью будет глав­ное окно при­ложе­ния. Зарезер­виру­ем для нее полосу в вер­хней час­ти рабоче­го сто­ла. Это мож­но сде­лать в обра­бот­чике со­обще­ния WM_CREATE, которое отправ­ляет­ся опе­раци­онной сис­темой окну при­ложе­ния непос­редс­твен­но перед тем, как отоб­разить его на экра­не. Для это­го в начале окон­ной про­цеду­ры WindowProc вста­вим стро­ки перехо­да к обра­бот­чику сооб­щения:

cmp [wmsg],WM_CREATE
je .wmcreate

и напишем сам обра­бот­чик перед мет­кой .wmdestroy:

.wmcreate:
stdcall wmCreateProc, [hwnd]
jmp .finish

info

Мет­ки, которые начина­ются с точ­ки, явля­ются локаль­ными по отно­шению к про­цеду­ре, где они исполь­зуют­ся (в дан­ном слу­чае — WindowProc). Это еще одна фиш­ка Flat Assembler, которая поз­воля­ет не бес­поко­ить­ся о том, что в раз­ных про­цеду­рах име­на меток могут пов­торять­ся.

Наш обра­бот­чик вызыва­ет пока еще не сущес­тву­ющую про­цеду­ру wmCreateProc и переда­ет ей зна­чение манипу­лято­ра соз­данно­го окна. В этой про­цеду­ре надо опи­сать дей­ствия по резер­вирова­нию полосы и позици­они­рова­нию глав­ного окна, пос­ле чего обну­лить регистр EAX для сиг­нализи­рова­ния об успешном завер­шении про­цеду­ры. Если пос­ле обра­бот­ки сооб­щения WM_CREATE зна­чение регис­тра EAX будет рав­но (-1), опе­раци­онная сис­тема вос­при­мет это как сиг­нал о проб­леме, что при­ведет к завер­шению работы прог­раммы. Текст про­цеду­ры wmCreateProc мож­но раз­местить пос­ле опе­рато­ра endp, зак­рыва­юще­го блок опи­сания окон­ной про­цеду­ры WindowProc:

proc wmCreateProc,hwnd
invoke MessageBox,[hwnd],_title,_class,MB_OK+MB_ICONINFORMATION
xor eax,eax
ret
endp

info

Вот про­межу­точ­ный вари­ант прог­раммы, который выводит отла­доч­ное сооб­щение: appbar-ver1.asm.

Про­цеду­ра wmCreateProc в таком виде не дела­ет ничего полез­ного, но при запус­ке прог­раммы выводит окно с информа­цион­ным сооб­щени­ем, которое дает понять, что на этом эта­пе все работа­ет так, как ожи­дает­ся.

info

Вни­матель­но сле­ди за тем, что­бы количес­тво и порядок аргу­мен­тов в коман­де вызова про­цеду­ры всег­да соот­ветс­тво­вали количес­тву и поряд­ку парамет­ров в ее опи­сании. FASMW это не кон­тро­лиру­ет, и, если допус­тить неб­режность, мож­но получить труд­но обна­ружи­ваемые ошиб­ки.

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    3 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии