cleanup();
exit(1);
}
if ((emm_save = (PMAP *) malloc(context_bytes)) == NULL) {
printf("snapshot: Couldn't allocate %d bytes for context
save area", context_bytes);
cleanup();
exit(1);
}
/*установить обpаботчик прерывания для перехватывания запросов
печати экрана*/
old_int5 = _dos_getvect(PRTSC_INT); /*сохранить старый век-
тор прерывания*/
_dos_setvect(PRTSC_INT, int5_isr); /*установить новый век-
тор прерывания*/
printf("snapshot: print screen interrupt handler is installed\n");
isr_status = 1;
/* пусть новый драйвер обслуживает прерывания*/
printf("snapshot: print screen interrupt handler is activated\n");
}
/* снять программу, резидентную после завершения, из памяти
по запросу пользователя */
terminate()
{
int rc;
unsigned int tsr_psp; /*префиксный программный сегмент
активной программы, резидентной по завершении*/
unsigned int far *envptr; /*указатель среды программы, ре-
зидентной по завершении*/
void (interrupt far *our_int5)(); /*адрес установленной прог-
раммы, резидентной по завершении*/
/* приостановить обработку прерываний печати экрана */
isr_status = 0;
printf("snapshot: print screen interrupt handler
deactivated\n");
/* отображение в страницу, содержащую индекс экрана */
if (rc = EMSMapHandlePage(emm_handle, 0, 0)) {
DisplayError(rc);
cleanup();
- 7-85 -
exit(1);
}
/*получить адресуемость для структуры данных индексов экра-*/
/*нов в pасшиpенной памяти, так чтобы мы могли получить ад-*/
/*рес программы обслуживания прерывания, которую мы установ-*/
/*вили, когда данная программа стартовала*/
ip = (SCR_INDEX far *) page_frame;
our_int5 = ip->scr_int5; /*получить запомненный адрес
программы обслуживания прерывания*/
/* освободить pасшиpенную память */
cleanup();
printf("snapshot: expanded memory handle %d deallocated\n",
emm_handle);
/* если никакой другой драйвер печати экрана не был установ-*/
/*лен перед нами, отключить программу обслуживания прерыва-*/
/*ния и вновь установить программу*/
if (_dos_getvect(PRTSC_INT) == our_int5) { /*наша программа
обслуживания прерывания - первая*/
/*восстановить старый вектор прерывания печати экрана */
_dos_setvect(PRTSC_INT, old_int5);
printf("snapshot: old print screen interrupt handler
restored\n");
/* освободить строки среды программы, резидентной по завер-
шении, и программный сегмент*/
tsr_psr = FP_SEG(our_int5) - 16; /*PSP начинается за 1666
параграфов до сегмента кода*/
printf("snapshot: deallocating TSR at segment [%04X]\n",
tsr_psp);
FP_SEG(envptr) = tsr_psp; /*указатель среды - по смеще-
нию*/
FP_OFF(envptr) = 0x2C; /* 2Ch в префикс сегмента про-
граммы*/
_dos_freemem(*envptr); /*освободить строки среды*/
_dos_freemem(tsr_psp); /*освободить программный сег-
мент*/
} else /*наша программа обслуживания прерывания не является
первой в цепи, нельзя снимать программу, резидентную
после завершения*/
printf("snapshot: cannot deallocate TSR - print screen ISR
is not first in chain\n");
}
/*процесс командной строки переключается в форму /L, где */
/*'L' - идентификация переключателя по одному символу. Воз-*/
/*вращается индекс первого элемента в массиве указателей, */
/*следующем за переключателями*/
- 7-86 -
get_opts(cnt, ptr)
int cnt;
char *ptr;
{
int argc;
terminate_flag = 0; /*сбросить флаг завершения*/
arc = 1;
while (*++ptr)[0] == '/' {
switch(*ptr)[1]) {
case '?' /*команда отображения и исполь-
зование переключателей*/
printf("snapshot: saves text screen images to
expanded memory\n");
printf("usage: snapshot [/X]\n");
printf(" /X - terminates snapshot");
exit(0);
break;
case 'x': /*завершает запрос*/
case 'X':
terminate_flag = 1;
break;
default: /*неизвестный переключатель*/
printf("'%c' is an unknown option\n", (*ptr)[1]));
break;
}
argc++;
}
return(argc);
}
-------------------------------------------------------------------
Листинг 7-9. PLAYBACK.C
-------------------------------------------------------------------
/*
Имя: PLAYBACK.C
Назначение: Распечатка образов текстовых экранов, сохра-
ненных в pасшиpенной памяти программой SNAPSHOT, в стан-
дартный выходной файл DOS.
*/
#include
#include
#include
#include
#include
- 7-87 -
#include "emmconst.h" /*константы менеджеpа pасшиpенной памяти*/
#include "emmtypes.h" /*структуры данных менеджеpа pасшиpенной
памяти*/
#include "emmerr.h" /*коды ошибок менеджеpа pасшиpенной памяти*/
#include "emmfunc.h" /*объявления функций менеджеpа pасшиpенной
памяти*/
#define DisplayError(rc) ShowEMMErr(rc, __LINE__, __FILE__)
#define HANDLE_NAME "SNAPSHOT" /*имя обpаботчика pасшиpенной
памяти/*
#define MAX_SCR 500 /*максимальное кол-во сохра-
няемых экранов*/
#define SCR_COLS 80 /*предполагается 80 колонок,
позже можно корректировать*/
#pragma pack(1) /*структуры данных с байтовым
выравниванием*/
typedef struct scr { /*дескриптор данных экрана*/
unsigned int scr_page; /*страница pасшиpенной памяти для
начального экрана*/
unsigned int scr_offset; /*смещение pасшиpенной памяти для
начального экрана*/
unsigned int scr_width; /*кол-во колонок на экране*/
unsigned int scr_len; /*длина экрана в байтах*/
} SCR;
typedef struct scr_index { /*индексная структура экранов*/
void (interrupt far *scr_int5)(); /*указатель на нашу програм-
му обслуживания прерывания*/
unsigned int scr_count; /*текущее кол-во сохраненных
экранов*/
unsigned int scr_max; /*максимальное кол-во сохра-
ненных экранов*/
SCR scr_idx[MAX_SCR]; /*массив индексов экранов*/
} SCR_INDEX;
/*
Глобальные данные
*/
unsigned int emm_handle, /*обpаботчик pасшиpенной памяти*/
emm_pages; /*кол-во страниц, принадлежащих
обpаботчику*/
char far *page_frame; /*удаленный -> на кадр страниц
спецификации pасшиpенной памяти*/
SCR_INDEX far *ip; /*удаленный -> на индекс экрана*/
SCR far *sp; /*удаленный -> на дескриптор эк-
рана*/
MOVE_XCHG mcb; /*структура "Передвинуть/обменять области*/
main()
{
unsigned int scan_code;
int emm_present, rc, current_screen;
- 7-88 -
char emm_ver[4];
/*тест наличия pасшиpенной памяти*/
if (rc = emm_exists(&emm_present)) {
/*тест наличия менеджеpа pасшиpенной памяти не прошел*/
printf("replay: EMM presence test failed, rc: %d", rc);
exit(2);
}
if (!emm_present) {
/* pасшиpенной памяти нет */
printf("replay: No expanded memory is present");
exit(1);
}
/*получить версию спецификации pасшиpенной памяти,поддерживае-
мую данным менеджеpом pасшиpенной памяти*/
if (rc = EMSGetVersion(emm_ver)) {
DisplayError(rc);
exit(1);
}
/* убедитесь, что версия не ниже 4.0 */
if (*emm_ver < '4') { /*требуется спецификация pасшиpенной
памяти LIM не ниже 4.0*/
printf("replay: Unsupported EMM version detected: %s,
LIM EMS 4.0 or greater is required", emm_ver);
exit(1);
}
/* получить указатель на кадр страниц спецификации pасшиpен-
ной памяти */
if (rc = EMSGetFrameAddr(&page_frame)) {
DisplayError(rc);
exit(1);
}
/* Поиск обpаботчика, содержащего запомненные экраны */
if (rc = EMSSearchHandleName(HANDLE_NAME, &emm_handle)) {
DisplayError(rc);
exit(1);
}
/* отобразить в страницу, содержащую индекс экрана */
if (rc = EMSMapHandlePage(emm_handle, 0, 0)) {
DisplayError(rc);
exit(1);
}
/* получить адресуемость на структуру данных индексов