Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Создание эффективных приложений для Windows Джеффри Рихтер 2004 (Книга).pdf
Скачиваний:
375
Добавлен:
15.06.2014
Размер:
8.44 Mб
Скачать

/SECTION:имя,атрибуты

За двоеточием укажите имя раздела, атрибуты которого Вы хотите изменить В нашем примере нужно изменить атрибуты раздела Shared, поэтому ключ должен выг лядеть так

/SECTION:Shared,RWS

После запятой мы задаем требуемые атрибуты При этом используются такие со кращения R (READ), W (WRITE), E (EXECUTE) и S(SHARED) В данном случае мы ука чали, что раздел Shared должен быть «читаемым», «записываемым" и "разделяемым» Если Вы хотите изменить атрибуты более чем у одного раздела, указывайте ключ /SECTION для каждого такого раздела

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

#pragma comment(linker, /SECTION Shared,RWS )

Эта строка заставляет компилятор включить строку "/SECTION Shared,RWS" в осо бый раздел drectve Компоновщик, собирая OBJ-модули, проверяет этот раздел в каж дом OBJмодуле и действует так, словно все эти строки переданы ему как аргументы в командной строке Я всегда применяю этот оченъ удобный метод перемещая файл исходного кода в новый проект, не надо изменять никаких параметров в диалоговом окне Project Settings в

Visual C++

Хотя создавать общие разделы можно, Microsoft нс рекомендует это делать Во первых, разделение памяти таким способом может нарушить защиту Во вторых, на личие общих переменных означает, что ошибка в одном приложении повлияет на другое, так как этот блок данных нс удастся защитить от случайной записи

Представьте, Вы написали два приложения, каждое из которых требует от пользо вателя вводить пароль При этом Вы решили чуть-чуть облегчить жизнь пользовате лю если одна из программ уже выполняется на момент запуска другой, то вторая счи тывает пароль из общей памяти Так что пользователю не пужно повторно вводить пароль, если одно из приложений уже запущено

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

Трудолюбивая хакерская программа может также предпринять серию попыток угадать пароль, записывая его варианты в общую память А угадав, сможет посылать любые команды этим двум приложениям Данную проблему можно было бы решить, если бы существовал какой-нибудь способ разрешать загрузку ULL только определен ным программам Но пока эю невозможно — любая протрамма, вызвав IoadLibrary, способна явно загрузить любую DLL

Программа-пример Applnst

Эта программа, "17 AppInst.exe" (см листинг на рис 17-1), демонстрирует, как выяс нить, сколько экземпляров приложения уже выполняется в системе Файлы исходно го кода и ресурсов этои программы находятся в каталоге 17-AppInst на компакт-дис

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

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

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

Где-то в начале файла AppInst.cpp Вы заметите следующие строки:

//указываем компилятору поместить эту инициализированную переменную

//в раздел Shared, чтобы она стала диступной всем окземплярам программы

#pragma data_seg("Shared")

volatile LONG g_lApplicationInstances = 0; #pragma data_seg()

//указываем компоновщику, что раздел Shared должен быть

//читаемым, записываемым и разделяемым

#pragma comment(linker, "/Section.Shared,RWS")

В этих строках кода создается раздел Shared c атрибутами защиты, которые раз решают его чтение, запись и разделение. Внутри него находится одна переменная, g_lApplicationInstances, доступная всем экземплярам программы. Заметьте, что для этой переменной указан спецификатор vokitile, чтобы оптимизатор не слишком с ней ум ничал.

При выполнении функции _tWinMain каждого экземпляра значение переменной g_lApplicattonInstances увеличивается на 1, а перед выходом ич _tWinMain — уменьша ется на 1. Я изменяю ее знячение с помощью функции InterlockedExchangeAdd, так как эта переменная является общим ресурсом для нескольких потоков.

Когда на экране появляется диалоговое окпо каждого экземпляра программы, вызывается функция Dlg__OnJnitDialog. Она рассылает всем окнам верхнего уровня зарегиорированное оконное сообщение (идентификатор которого содержится в переменной g_aMsgAppInstCоuntUpdate).

PostMessage(HWND_BROADCAST, g_aMsgAppInstCountUpdate, 0, 0);