Операционная система Microsoft Windows 3.1 для программиста© Александр Фролов, Григорий ФроловТом 13, М.: Диалог-МИФИ, 1993, 284 стр. 2.5. Работа с локальной таблицей дескрипторовДля полноты описания мы расскажем вам о функциях, позволяющих модифицировать локальную таблицу дескрипторов, создавая в ней новые дескрипторы или изменяя существующие (виртуальные драйвера могут выполнять аналогичные действия с глобальной таблицей дескрипторов, пользуясь специальным набором функций). Эти функции не рекомендуется использовать без крайней необходимости. Функция AllocSelector позволяет создать в локальной таблице дескрипторов новый дескриптор или скопировать существующий: UINT WINAPI AllocSelector(UINT uSelector); Если параметр uSelector перед вызовом функции содержит селектор, для которого в таблице дескрипторов есть дескриптор, функция AllocSelector копирует этот дескриптор и возвращает селектор, соответствующий копии. Если же этот параметр равен нулю, в локальной таблице дескрипторов создается новый неинициализированный дескриптор, при этом функция возвращает значение селектора, соответствующее созданному дескриптору. При ошибке возвращается нулевое значение. Если созданный дескриптор больше не нужен, его следует удалить при помощи функции FreeSelector : UINT WINAPI FreeSelector(UINT uSelector); Параметр функции должен содержать селектор, соответствующий удаляемому дескриптору. Если функция выполнилась без ошибок, она возвращает нулевое значение. В случае ошибки возвращается значение параметра uSelector. Перед использованием нового дескриптора его следует проинициализировать - установить базовый адрес и предел. Для установки базового адреса следует воспользоваться функцией SetSelectorBase , которая впервые появилась в составе программного интерфейса Windows версии 3.1: UINT WINAPI SetSelectorBase(UINT uSelector, DWORD dwBase); Для дескриптора, соответствующего селектору uSelector, устанавливается значение линейного адреса, равное dwBase. Если функция выполнилась успешно, она возвращает значение параметра uSelector. В случае ошибки возвращается нулевое значение. С помощью функции GetSelectorBase вы можете определить линейный адрес для любого существующего селектора: DWORD WINAPI GetSelectorBase(UINT uSelector); При помощи функции SetSelectorLimit вы можете определить предел сегмента, адресуемого селектором uSelector: UINT WINAPI SetSelectorLimit(UINT uSelector, DWORD dwLimit); Предел сегмента задается параметром dwLimit. Для процессора 80286 предел не должен превосходить величины 0x10000. О пределах сегментов вы можете прочитать в шестом томе "Библиотеки системного программиста", который называется "Защищенный режим процессоров Intel 80286/80386/80486". Функция GetSelectorLimit позволяет вам для заданного селектора uSelector определить предел сегмента: DWORD WINAPI GetSelectorLimit(UINT uSelector); С помощью функции LockSegment вы можете зафиксировать сегмент, соответствующий селектору uSelector: HGLOBAL WINAPI LockSegment(UINT uSelector); Если в качестве параметра этой функции передать значение -1, функция зафиксирует текущий сегмент данных. Возвращаемое значение определяет зафиксированный сегмент данных или NULL, если сегмент был удален или произошла ошибка. После использования зафиксированный сегмент необходимо расфиксировать при помощи функции UnlockSegment : void WINAPI UnlockSegment(UINT uSelector); В файле windows.h определены макрокоманды LockData и UnlockData , предназначенные, соответственно, для фиксирования и расфиксирования текущего сегмента данных: #define LockData(dummy) LockSegment((UINT)-1) #define UnlockData(dummy) UnlockSegment((UINT)-1) Если вам необходимо выполнить код, расположенный в сегменте данных, вы можете выполнить преобразование селекторов, вызвав функцию AllocDStoCSAlias : UINT WINAPI AllocDStoCSAlias(UINT uSelector); В качестве параметра этой функции передается селектор сегмента данных, содержащего код. Функция создает новый дескриптор, описывающий данный сегмент как сегмент кода и возвращает соответствующий селектор. После использования полученный селектор следует освободить при помощи функции FreeSelector. Функция PrestoChangoSelector создает селектор кодового сегмента, соответствующий селектору сегменту данных или наоборот, селектор сегмента данных, соответствующий сегменту кода: UINT WINAPI PrestoChangoSelector( UINT sourceSel, UINT destSel); Параметр sourceSel задает исходный селектор, который будет преобразован. Параметр destSel задает селектор, полученный при помощи функции AllocSelector. Дескриптор, соответствующий этому селектору, получит новые значения атрибутов, которые будут соответствовать атрибутам преобразуемого селектора. |